function.c
来自「ztscards」· C语言 代码 · 共 613 行
C
613 行
#include "ztsCards.h"
//产生随机牌局号///////////////////////////////////////////////////////////////
int GenerateNum()
{
int n;
srand (time (0));
n = rand ();
n = rand ();
do
{
n = rand();
} while (n<1 || n>32000);
return n;
}
//根据随机牌局号计算发牌顺序///////////////////////////////////////////////////
void SetCardsOrder (int n)
{
DWORD Nums[52];
DWORD i, j, k, t=52;
for (i=0; i<52; i++)
Nums[i] = i;
for (i=0; i<8; i++)
for (j=0; j<21; j++)
Cards[i][j] = -1;
srand (n);
for (i=0; i<7; i++)
for (j=0; j<8; j++)
{
k = rand() % (t--);
Cards[j][i] = Nums[k];
Nums[k] = Nums[t];
if (t == 0)
break;
}
//初始化左右空当
for (i=0; i<4; i++)
{
SpaceLeft[i] = -1;
SpaceRight[i] = -1;
}
}
//绘制中间的头像///////////////////////////////////////////////////////////////
void DrawLogo (HDC hdc, int n)
{
HDC hMemDC;
HBITMAP hBmp, hBmp_Old;
if (n) //判断头像的方向
hBmp = LoadBitmap (hInst, MAKEINTRESOURCE(IDB_LOGORIGHT));
else
hBmp = LoadBitmap (hInst, MAKEINTRESOURCE(IDB_LOGOLEFT));
hMemDC = CreateCompatibleDC (hdc);
hBmp_Old = SelectObject (hMemDC, hBmp);
BitBlt (hdc, x_Logo+2, y_Logo+2, 32, 32, hMemDC, 0, 0, SRCCOPY);
SelectObject (hMemDC, hBmp_Old);
DeleteDC (hMemDC);
}
//绘制左边空当/////////////////////////////////////////////////////////////////
void DrawSpaceLeft (HDC hdc)
{
int i;
HDC hMemDC;
HBITMAP hBmp_Old;
hMemDC = CreateCompatibleDC (hdc);
hBmp_Old = SelectObject (hMemDC, hBmpSpace);
for (i=0; i<4; i++)
{
if (SpaceLeft[i] != -1)//如果当前位置有牌,则不绘制空当,在原位置绘制一张牌
{
if (ColumnSelected == i+8)
cdtDraw (hdc, i*nCardWidth, 0, SpaceLeft[i], mdHilite, RGB (0, 0x7a, 0));
else
cdtDraw (hdc, i*nCardWidth, 0, SpaceLeft[i], mdFace, RGB (0, 0x7a, 0));
}
else
BitBlt (hdc, i*nCardWidth, 0, nCardWidth, nCardHeight, hMemDC, 0, 0, SRCCOPY);
}
SelectObject (hMemDC, hBmp_Old);
DeleteDC (hMemDC);
}
//绘制右边空当/////////////////////////////////////////////////////////////////
void DrawSpaceRight (HWND hWnd, HDC hdc)
{
int i;
RECT rect;
HDC hMemDC;
HBITMAP hBmp_Old;
GetClientRect (hWnd, &rect);
hMemDC = CreateCompatibleDC (hdc);
hBmp_Old = SelectObject (hMemDC, hBmpSpace);
for (i=0; i<4; i++)
{//从右往左绘制
if (SpaceRight[i] != -1)//如果当前位置有牌,则不绘制空当,在原位置绘制一张牌
cdtDraw (hdc, (rect.right-rect.left)-(i+1)*nCardWidth, 0, SpaceRight[i], mdFace, RGB (0, 0x7a, 0));
else
BitBlt (hdc, (rect.right-rect.left)-(i+1)*nCardWidth, 0, nCardWidth, nCardHeight, hMemDC, 0, 0, SRCCOPY);
}
SelectObject (hMemDC, hBmp_Old);
DeleteDC (hMemDC);
}
//绘制某一列牌/////////////////////////////////////////////////////////////////
void DrawColumn (HDC hdc, int n, BOOL bClear) // n 表示哪一列,bClear 表示绘制前先清除
{
int i, j;
RECT rect;
i = CalcColumnCards (n);
if (bClear)
{//绘制前是否先清除
rect.left = n * (nCardWidth + dxCard);
rect.right = rect.left + nCardWidth + dxCard;
rect.top = nCardHeight + 10;
rect.bottom = rect.top + 600;
FillRect (hdc, &rect, CreateSolidBrush (RGB (0, 0x7a, 0)));
}
for (j=0; j<=i; j++)
cdtDraw (hdc, (n+1)*dxCard+n*nCardWidth, j*dyCard+nCardHeight+10, Cards[n][j], mdFace, RGB (0, 0x7a, 0));
if (n == ColumnSelected)
{
j--;
cdtDraw (hdc, (n+1)*dxCard+n*nCardWidth, j*dyCard+nCardHeight+10, Cards[n][j], mdHilite, RGB (0, 0x7a, 0));
}
}
//计算可移动的牌的最大数目/////////////////////////////////////////////////////
//当把牌从一列移到另一列(非空列)时采用这个函数
int CalcSpaceAll (BOOL bEmpty) //bEmpty 表示把牌从一列移到一个空列
{
int n1=0, n2=1;
int i;
for (i=0; i<4; i++)
{//计算左上方的空当数
if (SpaceLeft[i] == -1)
n1++;
}
for (i=0; i<8; i++)
{//计算空出来的列数
if (Cards[i][0] == -1)
n2++;
}
if (bEmpty)
n2--;
//可移动的牌的最大数目
//左上方的 1 个空当可以移动 2 张牌,2 个空当可以移动 3 张牌,……
//空出来几列相当于可移动的牌数要翻几倍
return (n1+1)*n2;
}
//计算某一列的牌数/////////////////////////////////////////////////////////////
int CalcColumnCards (int n)
{
int i;
i = 0;
while (Cards[n][i] != -1)
i++;
i--;
//返回的牌数从 0 开始算的,比如返回 5 表示有 6 张牌
return i;
}
//判断后一张牌是否能够放在前一张牌上面/////////////////////////////////////////
BOOL IsMatch (int m, int n)
{
switch (n%4)
{
case 0://梅花
if ((m == n+5) || (m == n+6))
return TRUE;
else
return FALSE;
case 1://方块
if ((m == n+3) || (m == n+6))
return TRUE;
else
return FALSE;
case 2://红桃
if ((m == n+2) || (m == n+5))
return TRUE;
else
return FALSE;
case 3://黑桃
if ((m == n+2) || (m == n+3))
return TRUE;
else
return FALSE;
}
return FALSE;
}
//判断是不是一张废牌///////////////////////////////////////////////////////////
BOOL IsNoUseCards (int n)
{
int i, j, k;
BOOL flag = TRUE;
switch (n%4)
{
case 0://梅花
for (i=0; i<4; i++)
{//判断空当中的牌
if ((SpaceLeft[i] % 4) == 0)
{//判断同花色的牌
if (SpaceLeft[i] < n)
{
flag = FALSE;
return flag;
}
}
if (((SpaceLeft[i] % 4) == 1) || ((SpaceLeft[i] % 4) == 2))
{//判断相反花色的牌
if (SpaceLeft[i] < n)
{
flag = FALSE;
return flag;
}
}
}
for (i=0; i<8; i++)
{
k = CalcColumnCards (i);
for (j=0; j<=k; j++)
{
if ((Cards[i][j] % 4) == 0)
{//判断同花色的牌
if (Cards[i][j] < n)
{
flag = FALSE;
return flag;
}
}
if (((Cards[i][j] % 4) == 1) || ((Cards[i][j] % 4) == 2))
{//判断相反花色的牌
if (Cards[i][j] < n)
{
flag = FALSE;
return flag;
}
}
}
}
break;
case 3://黑桃
for (i=0; i<4; i++)
{//判断空当中的牌
if ((SpaceLeft[i] % 4) == 3)
{//判断同花色的牌
if (SpaceLeft[i] < n)
{
flag = FALSE;
return flag;
}
}
if (((SpaceLeft[i] % 4) == 1) || ((SpaceLeft[i] % 4) == 2))
{//判断相反花色的牌
if (SpaceLeft[i]+2 < n)
{
flag = FALSE;
return flag;
}
}
}
for (i=0; i<8; i++)
{
k = CalcColumnCards (i);
for (j=0; j<=k; j++)
{
if ((Cards[i][j] % 4) == 3)
{//判断同花色的牌
if (Cards[i][j] < n)
{
flag = FALSE;
return flag;
}
}
if (((Cards[i][j] % 4) == 1) || ((Cards[i][j] % 4) == 2))
{//判断相反花色的牌
if (Cards[i][j]+2 < n)
{
flag = FALSE;
return flag;
}
}
}
}
break;
case 1://方块
for (i=0; i<4; i++)
{//判断空当中的牌
if ((SpaceLeft[i] % 4) == 1)
{//判断同花色的牌
if (SpaceLeft[i] < n)
{
flag = FALSE;
return flag;
}
}
if (((SpaceLeft[i] % 4) == 1) || ((SpaceLeft[i] % 4) == 2))
{//判断相反花色的牌
if (SpaceLeft[i]+1 < n)
{
flag = FALSE;
return flag;
}
}
}
for (i=0; i<8; i++)
{
k = CalcColumnCards (i);
for (j=0; j<=k; j++)
{
if ((Cards[i][j] % 4) == 1)
{//判断同花色的牌
if (Cards[i][j] < n)
{
flag = FALSE;
return flag;
}
}
if (((Cards[i][j] % 4) == 0) || ((Cards[i][j] % 4) == 3))
{//判断相反花色的牌
if (Cards[i][j]+1 < n)
{
flag = FALSE;
return flag;
}
}
}
}
break;
case 2://红桃
for (i=0; i<4; i++)
{//判断空当中的牌
if ((SpaceLeft[i] % 4) == 2)
{//判断同花色的牌
if (SpaceLeft[i] < n)
{
flag = FALSE;
return flag;
}
}
if (((SpaceLeft[i] % 4) == 1) || ((SpaceLeft[i] % 4) == 2))
{//判断相反花色的牌
if (SpaceLeft[i]+2 < n)
{
flag = FALSE;
return flag;
}
}
}
for (i=0; i<8; i++)
{
k = CalcColumnCards (i);
for (j=0; j<=k; j++)
{
if ((Cards[i][j] % 4) == 2)
{//判断同花色的牌
if (Cards[i][j] < n)
{
flag = FALSE;
return flag;
}
}
if (((Cards[i][j] % 4) == 0) || ((Cards[i][j] % 4) == 3))
{//判断相反花色的牌
if (Cards[i][j]+2 < n)
{
flag = FALSE;
return flag;
}
}
}
}
break;
default:
flag = FALSE;
}
return flag;
}
//把某一列(包括空当)的最后一张牌收进右边空当/////////////////////////////////
void PutInSpaceRight (HWND hWnd, int n)
{
int i, j;
if (n < 8)
{
i = CalcColumnCards(n);
j = Cards[n][i];
Cards[n][i] = -1;
DrawColumn (GetDC (hWnd), n, TRUE);
}
else
{
j = SpaceLeft[n-8];
SpaceLeft[n-8] = -1;
DrawSpaceLeft (GetDC (hWnd));
}
for (i=0; i<4; i++)
{
if (SpaceRight[i] == -1)
{
SpaceRight[i] = j;
DrawSpaceRight (hWnd, GetDC (hWnd));
break;
}
else if ((j % 4) == (SpaceRight[i] % 4))
{
SpaceRight[i] = j;
DrawSpaceRight (hWnd, GetDC (hWnd));
break;
}
}
}
//把没有了利用价值的牌收集到右边空当///////////////////////////////////////////
BOOL CollectNoUseCards (HWND hWnd)
{
int i, j;
BOOL flag = FALSE;
for (i=0; i<4; i++)
{
if (IsNoUseCards (SpaceLeft[i]))
{
PutInSpaceRight (hWnd, i+8);
flag = TRUE;
}
}
for (i=0; i<8; i++)
{
j = CalcColumnCards (i);
if (j == -1)
continue;
if (IsNoUseCards (Cards[i][j]))
{
PutInSpaceRight (hWnd, i);
flag = TRUE;
}
}
return flag;
}
//判断牌局有没有结束///////////////////////////////////////////////////////////
BOOL IsWin (HWND hWnd)
{
int i, j;
for (i=0; i<4; i++)
{
if (SpaceLeft[i] != -1)
{
return FALSE;
}
}
for (i=0; i<8; i++)
for (j=0; j<21; j++)
{
if (Cards[i][j] != -1)
return FALSE;
}
return TRUE;
}
//判断是否输掉了当前局/////////////////////////////////////////////////////////
BOOL IsLose (HWND hWnd)
{
int i, j, m, n;
//看有没有空当
for (i=0; i<4; i++)
{
if (SpaceLeft[i] == -1)
return FALSE;
}
//看有没有空列
for (i=0; i<8; i++)
{
j = CalcColumnCards (i);
if (j == -1)
return FALSE;
}
//看空当中的牌有没有能够拿下来放在任何一列上
for (i=0; i<4; i++)
{
for (j=0; j<8; j++)
{
m = CalcColumnCards (j);
if (IsMatch (Cards[j][m], SpaceLeft[i]))
return FALSE;
}
}
//看空当中的牌能不能互相移动
for (i=0; i<8; i++)
{
for (j=0; j<8; j++)
{
m = CalcColumnCards (i);
n = CalcColumnCards (j);
if (IsMatch (Cards[j][n], Cards[i][m]))
return FALSE;
}
}
return TRUE;
}
//清扫战场,看有没有废牌可以回收,赢了还是输了等等/////////////////////////////
void SweepWar (HWND hWnd)
{
int k;
//回收废牌
while (CollectNoUseCards (hWnd))
;
if (IsWin (hWnd))
{//赢了
bPlaying = FALSE;
cur_wins++;
won++;
if (stype == 1)
streak++;
else
{
stype = 1;
streak = 1;
}
if (stype == 1)
{
if (streak > wins)
wins = streak;
}
k = DialogBoxParam (hInst, MAKEINTRESOURCE (DLG_WIN), hWnd, DlgWinProc, 0);
if (k == 2)
{
SendMessage (hWnd, WM_COMMAND, MAKEWPARAM (IDM_GAME_SELECT, 0), 0);
}
else if (k == 1)
{
SendMessage (hWnd, WM_COMMAND, MAKEWPARAM (IDM_GAME_START, 0), 0);
}
}
if (IsLose (hWnd))
{//输了
bPlaying = FALSE;
cur_losses++;
lost++;
if (stype == -1)
streak++;
else
{
stype = -1;
streak = 1;
}
if (stype == -1)
{
if (streak > losses)
losses = streak;
}
k = DialogBoxParam (hInst, MAKEINTRESOURCE (DLG_LOSE), hWnd, DlgLoseProc, 0);
if (k == 2)
{
SendMessage (hWnd, WM_COMMAND, MAKEWPARAM (IDM_GAME_RESTART, 0), 0);
}
else if (k == 1)
{
SendMessage (hWnd, WM_COMMAND, MAKEWPARAM (IDM_GAME_START, 0), 0);
}
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?