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 + -
显示快捷键?