简单五子棋-win32API(3)

1)添加键盘响应,通过键盘控制标框位置并安放棋子;

2)修改了消息框,不在是单次游玩;

3)代码:

#include<Windows.h>
#include<windowsx.h>
#include<strsafe.h>
//回调函数,windows自己调用
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int End();
void DrawBox(HDC hdc, int x, int y);
void Return();

//窗口初始宽高,宽高比
#define w_h 1.28
int hight = 600;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPreInstance, PSTR szCmdLine, int iCmdShow)
{
	static TCHAR szAppName[] = TEXT("MyWindows");
	HWND hWnd;	//句柄
	MSG msg;	//消息
	WNDCLASS wndClass;	//窗口类
						//设置窗口类的各项数据
	wndClass.style = CS_HREDRAW | CS_VREDRAW;	//调整窗口大小时是否重绘
	wndClass.lpfnWndProc = WndProc;		//回调函数
	wndClass.cbClsExtra = 0;
	wndClass.cbWndExtra = 0;
	wndClass.hInstance = hInstance;	//实例句柄
	wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);	//图标
	wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);		//光标
	wndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
	wndClass.lpszMenuName = NULL;
	wndClass.lpszClassName = szAppName;
	//注册该窗口类
	if (!RegisterClass(&wndClass))
	{
		MessageBox(NULL, TEXT("这个程序需要在windowsNT才能执行!"), szAppName, MB_ICONERROR);
		return 0;
	}
	//设置窗口具体特征(分化)
	hWnd = CreateWindow(szAppName, TEXT("五子棋"), WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, CW_USEDEFAULT, (int)(hight*w_h), hight,
		NULL, NULL, hInstance, NULL);

	ShowWindow(hWnd, iCmdShow);
	UpdateWindow(hWnd);
	//消息循环,windows核心
	while (GetMessage(&msg, NULL, 0, 0))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);	//调用窗口过程函数(回调函数)
	}

	return msg.wParam;
}

//棋盘范围
RECT chess;
//棋盘点
typedef struct CHESS
{
	LONG x;
	LONG y;
	int c;	//颜色
}Chess[15][15];
Chess ptChess;
//棋子宽度
LONG pieceWidth;
//棋子颜色\胜手
#define UNKNOW 0
#define BLACK 1
#define WHITE 2
//平局
#define LEVEL 3
//棋子
typedef struct PIECE
{
	int i;
	int j;
	int color;
}Piece[255];
Piece pieces;
int ip = 0;
//当前手的棋子颜色
int nowColor = BLACK;
void Reverse()
{
	switch (nowColor)
	{
	case WHITE:
		nowColor = BLACK;
		break;
	case BLACK:
		nowColor = WHITE;
		break;
	}
}
//控制台
RECT contralRect;
//标框,标识棋盘点位,响应键盘鼠标
struct BOX
{
	int i, j;
}box;

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	HDC hdc;
	PAINTSTRUCT ps;

	static int cxClient, cyClient;
	static HBRUSH hOldBrush, hBlackBrush, hWhiteBrush;
	static HPEN hOldPen, hRedPen;
	POINT ptClick;
	TCHAR szBuffer[30] = TEXT("%s棋赢了!\n是否开始下一局?"), szDest[30];

	int i, j;

	switch (message)
	{
	case WM_CREATE:
		//创建画刷,画笔
		hBlackBrush = CreateSolidBrush(RGB(0, 0, 0));
		hWhiteBrush = CreateSolidBrush(RGB(255, 255, 255));
		hRedPen = CreatePen(PS_ALTERNATE, 2, RGB(255, 0, 0));
		
		return 0;
	case WM_SIZE:
		cxClient = LOWORD(lParam);
		cyClient = HIWORD(lParam);
		//获取棋子宽度
		pieceWidth = min(cxClient, cyClient) / 18;
		//获取棋盘点
		for (int i = 0; i < 15; ++i)
		{
			for (int j = 0; j < 15; ++j)
			{
				ptChess[i][j].x = pieceWidth*(i + 2);
				ptChess[i][j].y = pieceWidth*(j + 2);
			}
		}
		//棋盘范围
		SetRect(&chess, pieceWidth, pieceWidth, pieceWidth * 17, pieceWidth * 17);
		//获取控制板
		contralRect.left = pieceWidth * 18;
		contralRect.bottom = cyClient - pieceWidth * 2;
		contralRect.right = cxClient-pieceWidth*2;
		contralRect.top = pieceWidth * 2;
		//获取标框
		box.i = 7;
		box.j = 7;

		return 0;
	case WM_LBUTTONDOWN:
		if (wParam != 0)	//消息来自鼠标
		{	//获取单击位置
			ptClick.x = GET_X_LPARAM(lParam);
			ptClick.y = GET_Y_LPARAM(lParam);
			//计算棋子安放位置
			i = (ptClick.x + pieceWidth / 2) / pieceWidth - 2;
			j = (ptClick.y + pieceWidth / 2) / pieceWidth - 2;
		}
		else	//消息来自键盘
		{
			i = box.i;
			j = box.j;
		}
		//判断棋子安放位置是否合理
		if (i < 0 || i>14 || j < 0 || j>14 || ptChess[i][j].c != UNKNOW)
		{
			return 0;
		}
		//载入棋子队列
		pieces[ip].i = i;
		pieces[ip].j = j;
		pieces[ip].color = nowColor;

		ptChess[i][j].c = nowColor;
		Reverse();
		ip++;
		if (wParam != 0)
		{
			//标框移动
			box.i = i;
			box.j = j;
		}
		//重绘
		InvalidateRect(hWnd, &chess, TRUE);
		return 0;
	case WM_RBUTTONDOWN:
		if (ip == 0)
		{
			return 0;
		}
		ip--;
		i = pieces[ip].i;
		j = pieces[ip].j;
		//值回溯
		ptChess[i][j].c = UNKNOW;
		pieces[ip].i = 0;
		pieces[ip].j = 0;
		pieces[ip].color = UNKNOW;
		//当前手颜色回复
		Reverse();
		//标框复位
		if (ip == 0)
		{
			box.i = 7;
			box.j = 7;
		}
		else
		{
			box.i = pieces[ip - 1].i;
			box.j = pieces[ip - 1].j;
		}
		//重绘
		InvalidateRect(hWnd, &chess, TRUE);
		return 0;
	case WM_KEYDOWN:
		switch (wParam)
		{
		case VK_UP:	box.j--; break;
		case VK_DOWN: box.j++; break;
		case VK_LEFT: box.i--; break;
		case VK_RIGHT: box.i++; break;
		case VK_RETURN:
		case VK_SPACE:
			SendMessage(hWnd, WM_LBUTTONDOWN, 0, 0);
			break;
		case VK_DELETE:
			SendMessage(hWnd, WM_RBUTTONDOWN, 0, 0);
			break;
		}
		box.i = (box.i + 15) % 15;
		box.j = (box.j + 15) % 15;
		InvalidateRect(hWnd, &chess, TRUE);
		return 0;
	case WM_PAINT:
		hdc = BeginPaint(hWnd, &ps);
		
		//绘制棋盘
		for (int i = 0; i < 15; ++i)
		{
			MoveToEx(hdc, ptChess[i][0].x, ptChess[i][0].y, NULL);
			LineTo(hdc, ptChess[i][14].x, ptChess[i][14].y);
		}
		for (int j = 0; j < 15; ++j)
		{
			MoveToEx(hdc, ptChess[0][j].x, ptChess[0][j].y, NULL);
			LineTo(hdc, ptChess[14][j].x, ptChess[14][j].y);
		}
		
		//绘制控制板
		FrameRect(hdc, &contralRect, hBlackBrush);
		//绘制标框
		hOldPen = SelectObject(hdc, hRedPen);
		i = ptChess[box.i][box.j].x;
		j = ptChess[box.i][box.j].y;
		DrawBox(hdc,i,j);
		SelectObject(hdc, hOldPen);
		//绘制棋子
		hOldBrush = SelectObject(hdc, hBlackBrush);
		for (int i = 0, j = 0, k = 0; k < ip; ++k)
		{
			if (pieces[k].color == UNKNOW)
				continue;
			if (pieces[k].color == BLACK)
				SelectObject(hdc, hBlackBrush);
			if (pieces[k].color == WHITE)
				SelectObject(hdc, hWhiteBrush);
			int i = pieces[k].i, j = pieces[k].j;
			Ellipse(hdc, ptChess[i][j].x - pieceWidth / 2, ptChess[i][j].y - pieceWidth / 2, ptChess[i][j].x + pieceWidth / 2, ptChess[i][j].y + pieceWidth / 2);
		}
		SelectObject(hdc, hOldBrush);
		//判断五子连珠
		switch (End())
		{
		case WHITE:
			SendMessage(hWnd, WM_CLOSE, WHITE, 0);
			break;
		case BLACK:

			SendMessage(hWnd, WM_CLOSE, BLACK, 0);
			break;
		}
		//判断棋盘占满
		if (ip == 255)
		{
			SendMessage(hWnd, WM_CLOSE, LEVEL, 0);
		}
		
		EndPaint(hWnd, &ps);
		return 0;
	case WM_CLOSE:
		switch (wParam)
		{
		case WHITE:
			StringCchPrintf(szDest, 30, szBuffer, TEXT("白"));
			if (MessageBox(hWnd, szDest, TEXT("GameOver"), MB_YESNO) == IDNO)
				DestroyWindow(hWnd);
			else
			{
				Return();
				InvalidateRect(hWnd, &chess, TRUE);
			}
				
			break;
		case BLACK:
			StringCchPrintf(szDest, 30, szBuffer, TEXT("黑"));
			if (MessageBox(hWnd, szDest, TEXT("GameOver"), MB_YESNO) == IDNO)
				DestroyWindow(hWnd);
			else
			{
				Return();
				InvalidateRect(hWnd, &chess, TRUE);
			}
			break;
		case LEVEL:
			StringCchPrintf(szDest, 30, TEXT("平局!"));
			if (MessageBox(hWnd, szDest, TEXT("GameOver"), MB_YESNO) == IDNO)
				DestroyWindow(hWnd);
			else
			{
				Return();
				InvalidateRect(hWnd, &chess, TRUE);
			}
			break;
		default:
			StringCchPrintf(szDest, 30, TEXT("对局尚未结束,是否离开游戏?"));
			if (MessageBox(hWnd, szDest, TEXT("End"), MB_YESNO) == IDYES)
				DestroyWindow(hWnd);
			break;
		}
		return 0;

	case WM_DESTROY:
		DeleteObject(hWhiteBrush);
		DeleteObject(hBlackBrush);
		DeleteObject(hRedPen);
		PostQuitMessage(0);
		return 0;
	}
	return DefWindowProc(hWnd, message, wParam, lParam);
}
//判断五子连珠
int End()
{
	int current = ip - 1;
	if (current < 8)
	{
		return UNKNOW;
	}
	int iTarget, i, j, x, y, color;
	i = pieces[current].i;
	j = pieces[current].j;
	color = pieces[current].color;
	//判断横向
	x = max(i - 4, 0);
	y = j;
	iTarget = 0;
	for (; x <= min(i + 4, 14); ++x)
	{
		if (ptChess[x][y].c == color)
		{
			++iTarget;
			if (iTarget == 5)
			{
				return color;
			}
		}
		else iTarget = 0;
	}
	//判断纵向
	x = i;
	y = max(j - 4, 0);
	iTarget = 0;
	for (; y <= min(j + 4, 14); ++y)
	{
		if (ptChess[x][y].c == color)
		{
			++iTarget;
			if (iTarget == 5)
			{
				return color;
			}
		}
		else iTarget = 0;
	}
	//判断斜向
	x = i - 4;
	y = j + 4;
		//越界
	if (x < 0 || y>14)
	{
		int temp = max(0 - x, y - 14);
		x += temp;
		y -= temp;
	}
	iTarget = 0;
	for (; ( y >= max(j - 4, 0)) && (x <= min(14, i + 4)); ++x, --y)
	{
		if (ptChess[x][y].c == color)
		{
			++iTarget;
			if (iTarget == 5)
			{
				return color;
			}
		}
		else iTarget = 0;
	}
	x = i - 4;
	y = j - 4;
	if (x < 0 || y < 0)
	{
		int temp = max(0 - x, 0 - y);
		x += temp;
		y += temp;
	}
	iTarget = 0;
	for (; (y <= min(j + 4, 14)) && (x <= min(14, i + 4)); ++x, ++y)
	{
		if (ptChess[x][y].c == color)
		{
			++iTarget;
			if (iTarget == 5)
			{
				return color;
			}
		}
		else iTarget = 0;
	}

	return UNKNOW;
}
//绘制标框
void DrawBox(HDC hdc,int x,int y)
{	//左上角
	MoveToEx(hdc, x - pieceWidth / 2, y - pieceWidth / 2, NULL);
	LineTo(hdc, x - pieceWidth / 4, y - pieceWidth / 2);
	MoveToEx(hdc, x - pieceWidth / 2, y - pieceWidth / 2, NULL);
	LineTo(hdc, x - pieceWidth / 2, y - pieceWidth / 4);
	//右上角
	MoveToEx(hdc, x + pieceWidth / 2, y - pieceWidth / 2, NULL);
	LineTo(hdc, x + pieceWidth / 4, y - pieceWidth / 2);
	MoveToEx(hdc, x + pieceWidth / 2, y - pieceWidth / 2, NULL);
	LineTo(hdc, x + pieceWidth / 2, y - pieceWidth / 4);
	//左下角
	MoveToEx(hdc, x - pieceWidth / 2, y + pieceWidth / 2, NULL);
	LineTo(hdc, x - pieceWidth / 4, y + pieceWidth / 2);
	MoveToEx(hdc, x - pieceWidth / 2, y + pieceWidth / 2, NULL);
	LineTo(hdc, x - pieceWidth / 2, y + pieceWidth / 4);
	//右下角
	MoveToEx(hdc, x + pieceWidth / 2, y + pieceWidth / 2, NULL);
	LineTo(hdc, x + pieceWidth / 4, y + pieceWidth / 2);
	MoveToEx(hdc, x + pieceWidth / 2, y + pieceWidth / 2, NULL);
	LineTo(hdc, x + pieceWidth / 2, y + pieceWidth / 4);
}
//棋盘回复函数
void Return()
{
	int i, j;
	for (i = 0; i < 15; ++i)
	{
		for (j = 0; j < 15; ++j)
		{
			ptChess[i][j].c = UNKNOW;
			pieces[i * 15 + j].i = 0;
			pieces[i * 15 + j].j = 0;
			pieces[i * 15 + j].color = UNKNOW;
		}
	}
	ip = 0;
	box.i = 7;
	box.j = 7;
	nowColor = BLACK;
}

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值