自己写了一个简单的五子棋给各位大神看看
这是我用 SDK 写的,很简单,基本功能是实现了{:5_109:}/* -------------------------------------------------------------------MyWindows.c -- 基本窗口模型
《Windows 程序设计(SDK)》视频教程
--------------------------------------------------------------------*/
#include <windows.h>
#include <strsafe.h>
#include<windowsx.h>
//判断白黑棋是否赢
boolblack_white_win(const POINT *PW, int w_num);
//一个画白色圆的函数 传入一个坐标
voidmy_Circle(HDC hdc, POINT cri);
//一个画黑色圆的函数 传入一个坐标
voidmy_Circle_b(HDC hdc, POINT cri);
//棋盘
void DrawSquare(HDC hdc, POINT point);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, 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("这个程序需要在 Windows NT 才能执行!"), szAppName, MB_ICONERROR);
return 0;
}
hwnd = CreateWindow(szAppName,
TEXT("鱼C工作室"),
WS_OVERLAPPEDWINDOW | WS_HSCROLL | WS_VSCROLL,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL);
ShowWindow(hwnd, iCmdShow);
UpdateWindow(hwnd);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
RECT rect;
static int cxClient, cyClient; //表是客户区的宽 和 高
size_tiTarget; //unsigent int 无符号整形 用来计算字符串长度
static int cx_char; //水平 与 垂直 方向字体的设置
static int cy_char;
//TEXTMETRIC 结构记录当前设备环境中有关字体的各种信息。
//结构成员的值的单位取决于设备环境中当前选定的映射模式,默认的映射模式是 MM_TEXT,所以它们的值是以像素为单位的
TEXTMETRIC tm; //指向 TEXTMETRIC 的指针
static TCHAR szBuffer = TEXT("五子棋少年的追梦之旅");
static TCHAR sz_rule = TEXT("规则:1.按鼠标左右键下棋 按左键白子先下 按右键黑子先下 2.任意一方五个棋子相连获得胜利");
static TCHAR wb_szstr;
int x, y , xPos , yPos; //xPos yPos 表示鼠标点击的坐标
POINT point;
static int numA = 0, numB = 0; //记录落子的个数
static POINT w_point; //记录白子的所有坐标
static POINT b_point; //记录黑子的所有坐标
int i;
//控制黑白子是否落下的开关( 1表示关 0表示开)
static int w_off = 0, b_off = 0;
//赢了后接受消息
int S_MSG;
switch (message)
{
case WM_CREATE:
hdc = GetDC(hwnd);
GetTextMetrics(hdc , &tm);
cx_char = tm.tmAveCharWidth;
cy_char = tm.tmHeight + tm.tmExternalLeading;
ReleaseDC(hwnd , hdc);
return 0;
case WM_SIZE:
cxClient = LOWORD(lParam); //获得客户区的宽
cyClient = HIWORD(lParam); // 获得客户区的高
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
GetClientRect(hwnd, &rect);
SetTextAlign(hdc,GetTextAlign(hdc) | TA_LEFT );
//绘制棋盘方格
StringCchLength(szBuffer , 128 , &iTarget);
TextOut(hdc, cxClient/2-100, cy_char, szBuffer, iTarget);
for (x = 40; x < cxClient-40; x+=20)
{
for (y = 40; y < cyClient-40; y += 20)
{
point.x = x;
point.y = y;
DrawSquare(hdc, point);
}
}
StringCchLength(sz_rule, 128, &iTarget);
TextOut(hdc, cy_char, cyClient-25, sz_rule, iTarget);
EndPaint(hwnd, &ps);
return 0;
//WM_LBUTTONUP 0x0202 释放鼠标左键
caseWM_LBUTTONUP:
hdc = GetDC(hwnd);
GetClientRect(hwnd, &rect);
xPos = GET_X_LPARAM(lParam);//GET_X_LPARAM(lParam) 返回坐标的 x 值;
yPos = GET_Y_LPARAM(lParam);//GET_Y_LPARAM(lParam) 返回坐标的 y 值;
//用户通常没办法将鼠标100%点中下棋子的位置,因此我们的程序应该自动找到最接近的下子位置
if (xPos % 20 >= 10)
xPos = xPos + 10 - xPos % 10;
else
xPos = xPos - xPos % 10;
if (yPos % 20 >= 10)
yPos = yPos + 10 - yPos % 10;
else
yPos = yPos - yPos % 10;
//画一个白色的圆
point.x = xPos;
point.y = yPos;
// 下的棋子的位置不能超界
if (point.x < 40 || point.y < 40)
{
ReleaseDC(hwnd, hdc);
return 0;
}
//判断与黑子的坐标是否重复
for (i = 0; i < numB; i++)
{
if (point.x == b_point.x && point.y == b_point.y )
{
ReleaseDC(hwnd, hdc);
return 0;
}
}
//判断白子有没有多画(只画一个白子)
if (w_off == 1)
{
ReleaseDC(hwnd, hdc);
return 0;
}
//记录下白子的坐标
w_point = point;
numA+=1;
StringCchPrintf(wb_szstr, 128, TEXT("%d 白棋坐标(%d , %d)"), numA ,point.x, point.y);
StringCchLength(wb_szstr, 128, &iTarget);
TextOut(hdc , rect.right-200 , 10 , wb_szstr, iTarget);
my_Circle(hdc , point);
w_off = 1;//画完白子后关了
b_off = 0; // 画完白子后开
//判断棋子是否赢
if (numA >= 5 && black_white_win(w_point , numA))
{
S_MSG = MessageBox(NULL , TEXT("恭喜白子获得胜利\n是不是要开始新的一局?") , TEXT("赢了。。赢了") , MB_YESNO);
if (IDYES == S_MSG)
{
for (int i = 0; i <numA; i++)
{
w_point.x = 0;
w_point.y = 0;
b_point.x = 0;
b_point.y = 0;
}
numB = 0;
numA = 0;
w_off = 0;
b_off = 0;
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
ReleaseDC(hwnd, hdc);
return 0;
}
}
ReleaseDC(hwnd , hdc);
return 0;
//WM_RBUTTONDOWN 0x0204 按下鼠标右键
case WM_RBUTTONDOWN:
hdc = GetDC(hwnd);
GetClientRect(hwnd, &rect);
xPos = GET_X_LPARAM(lParam);//GET_X_LPARAM(lParam) 返回坐标的 x 值;
yPos = GET_Y_LPARAM(lParam);//GET_Y_LPARAM(lParam) 返回坐标的 y 值;
//用户通常没办法将鼠标100%点中下棋子的位置,因此我们的程序应该自动找到最接近的下子位置
if (xPos % 20 >= 10)
xPos = xPos + 10 - xPos % 10;
else
xPos = xPos - xPos % 10;
if (yPos % 20 >= 10)
yPos = yPos + 10 - yPos % 10;
else
yPos = yPos - yPos % 10;
//画一个黑色的圆
point.x = xPos;
point.y = yPos;
// 下的棋子的位置不能超界
if (point.x < 40 || point.y < 40)
{
ReleaseDC(hwnd, hdc);
return 0;
}
//判断与白子的坐标是否重复
for (i = 0; i < numA; i++)
{
if (point.x == w_point.x && point.y == w_point.y )
{
ReleaseDC(hwnd, hdc);
return 0;
}
}
//判断黑子有没有多画(只画一个黑子)
if (b_off == 1)
{
ReleaseDC(hwnd, hdc);
return 0;
}
b_point = point;
numB+=1;
StringCchPrintf(wb_szstr, 128, TEXT("%d 黑棋坐标(%d , %d)"), numB, point.x, point.y);
StringCchLength(wb_szstr, 128, &iTarget);
TextOut(hdc, rect.left, 10, wb_szstr, iTarget);
//画黑子
my_Circle_b(hdc, point);
w_off = 0;//画完黑子后开
b_off = 1;//画完黑子后关了
//判断棋子是否赢
if (numB >= 5 && black_white_win(b_point, numB))
{
S_MSG = MessageBox(NULL, TEXT("恭喜黑子获得胜利\n是不是要开始新的一局?"), TEXT("赢了。。赢了"), MB_YESNO);
if (IDYES == S_MSG)
{
for (int i = 0; i < numB; i++)
{
b_point.x = 0;
b_point.y = 0;
w_point.x = 0;
w_point.y = 0;
}
numB = 0;
numA = 0;
w_off = 0;
b_off = 0;
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
ReleaseDC(hwnd, hdc);
return 0;
}
}
ReleaseDC(hwnd, hdc);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
voidmy_Circle(HDC hdc, POINT cri)
{
//根据中心点的坐标 确定左上角和右下角的坐标
RECT rect;
rect.right = cri.x - 10;
rect.top = cri.y - 10;
rect.left = cri.x + 10;
rect.bottom = cri.y + 10;
//画园
Ellipse(hdc, rect.right, rect.top, rect.left, rect.bottom);
return;
}
voidmy_Circle_b(HDC hdc, POINT cri)
{
//根据中心点的坐标 确定左上角和右下角的坐标
RECT rect;
//定义一个画刷类型
HBRUSHhBrush, holdBrush;
rect.right = cri.x - 10;
rect.top = cri.y - 10;
rect.left = cri.x + 10;
rect.bottom = cri.y + 10;
hBrush = (HBRUSH)GetStockObject(BLACK_BRUSH);//BLACK_BRUSH 黑色画刷
//SelectObject 函数用于选择一对象到指定的设备环境中,该新对象将替换先前的相同类型的对象
holdBrush = (HBRUSH)SelectObject(hdc, hBrush);
//画园
Ellipse(hdc, rect.right, rect.top, rect.left, rect.bottom);
SelectObject(hdc, holdBrush);
return;
}
void DrawSquare(HDC hdc, POINT point)
{
MoveToEx(hdc, point.x, point.y, NULL);
LineTo(hdc, point.x + 20, point.y);
LineTo(hdc, point.x + 20, point.y + 20);
LineTo(hdc, point.x, point.y + 20);
LineTo(hdc, point.x, point.y);
}
//判断白棋是否赢
boolblack_white_win(const POINT *PW, int w_num)
{
POINT temp;
POINT A;
int num_con = 0;
//遍历整个数组
for (int i = 0; i < w_num; i++)
{
//把要判断的白子赋给temp
temp = *(PW + i);
for (int a = 0 ; a < 4; a++ )
{
//同一方向的向右的四个棋子存入数组
A.x = temp.x + (a + 1) * 20;
A.y = temp.y;
}
//判断同一方向的向右的四个棋子是否在数组内
for (int b = 0; b < 4; b++)
{
for (int y = 0; y < w_num; y++)
{
if (A.x == (*(PW + y)).x && A.y == (*(PW + y)).y)
num_con++;
}
}
if (num_con == 4)
return true;
else
num_con = 0;
for (int a = 0; a < 4; a++)
{
//同一方向的向左的四个棋子存入数组
A.x = temp.x - (a + 1) * 20;
A.y = temp.y;
}
//判断同一方向的向左的四个棋子是否在数组内
for (int b = 0; b < 4; b++)
{
for (int y = 0; y < w_num; y++)
{
if (A.x == (*(PW + y)).x && A.y == (*(PW + y)).y)
num_con++;
}
}
if (num_con == 4)
return true;
else
num_con = 0;
for (int a = 0; a < 4; a++)
{
//同一方向的向上的四个棋子存入数组
A.x = temp.x;
A.y = temp.y - (a+1)*20;
}
//判断同一方向的向上的四个棋子是否在数组内
for (int b = 0; b < 4; b++)
{
for (int y = 0; y < w_num; y++)
{
if (A.x == (*(PW + y)).x && A.y == (*(PW + y)).y)
num_con++;
}
}
if (num_con == 4)
return true;
else
num_con = 0;
for (int a = 0; a < 4; a++)
{
//同一方向的向下的四个棋子存入数组
A.x = temp.x;
A.y = temp.y + (a + 1) * 20;
}
//判断同一方向的向下的四个棋子是否在数组内
for (int b = 0; b < 4; b++)
{
for (int y = 0; y < w_num; y++)
{
if (A.x == (*(PW + y)).x && A.y == (*(PW + y)).y)
num_con++;
}
}
if (num_con == 4)
return true;
else
num_con = 0;
for (int a = 0; a < 4; a++)
{
//同一方向的向左斜上的四个棋子存入数组
A.x = temp.x - (a + 1) * 20;
A.y = temp.y - (a + 1) * 20;
}
//判断同一方向的向左斜上的四个棋子是否在数组内
for (int b = 0; b < 4; b++)
{
for (int y = 0; y < w_num; y++)
{
if (A.x == (*(PW + y)).x && A.y == (*(PW + y)).y)
num_con++;
}
}
if (num_con == 4)
return true;
else
num_con = 0;
for (int a = 0; a < 4; a++)
{
//同一方向的向左斜下的四个棋子存入数组
A.x = temp.x - (a + 1) * 20;
A.y = temp.y + (a + 1) * 20;
}
//判断同一方向的向左斜下的四个棋子是否在数组内
for (int b = 0; b < 4; b++)
{
for (int y = 0; y < w_num; y++)
{
if (A.x == (*(PW + y)).x && A.y == (*(PW + y)).y)
num_con++;
}
}
if (num_con == 4)
return true;
else
num_con = 0;
for (int a = 0; a < 4; a++)
{
//同一方向的向右斜下的四个棋子存入数组
A.x = temp.x + (a + 1) * 20;
A.y = temp.y + (a + 1) * 20;
}
//判断同一方向的向右斜下的四个棋子是否在数组内
for (int b = 0; b < 4; b++)
{
for (int y = 0; y < w_num; y++)
{
if (A.x == (*(PW + y)).x && A.y == (*(PW + y)).y)
num_con++;
}
}
if (num_con == 4)
return true;
else
num_con = 0;
for (int a = 0; a < 4; a++)
{
//同一方向的向右斜上的四个棋子存入数组
A.x = temp.x + (a + 1) * 20;
A.y = temp.y - (a + 1) * 20;
}
//判断同一方向的向右斜上的四个棋子是否在数组内
for (int b = 0; b < 4; b++)
{
for (int y = 0; y < w_num; y++)
{
if (A.x == (*(PW + y)).x && A.y == (*(PW + y)).y)
num_con++;
}
}
if (num_con == 4)
return true;
else
num_con = 0;
}
return false;
}
页:
[1]