#include<graphics.h>
#include<iostream>
char board_data[3][3] =
{
{'-','-','-'},
{'-','-','-'},
{'-','-','-'}
};
char current_piece = 'O';
bool CheckWin(char c)//检测谁获胜
{
if (board_data[0][0] == c && board_data[0][1] == c && board_data[0][2] == c)//横线
return true;
if (board_data[1][0] == c && board_data[1][1] == c && board_data[1][2] == c)
return true;
if (board_data[2][0] == c && board_data[2][1] == c && board_data[2][2] == c)
return true;
if (board_data[0][0] == c && board_data[1][0] == c && board_data[2][0] == c)//竖线
return true;
if (board_data[0][1] == c && board_data[1][1] == c && board_data[2][1] == c)
return true;
if (board_data[0][2] == c && board_data[1][2] == c && board_data[2][2] == c)
return true;
if (board_data[0][0] == c && board_data[1][1] == c && board_data[2][2] == c)//斜线
return true;
if (board_data[0][2] == c && board_data[1][1] == c && board_data[2][0] == c)
return true;
return false;
}
bool CheckDraw()//检测是否为平局
{
for(size_t i=0;i<3;i++)
for (size_t j = 0; j < 3; j++)
{
if (board_data[i][j] == '-');
return false;
}
return true;
}
void DrawBoard()//绘制棋盘
{
line(0, 200, 600, 200);
line(0, 400, 600, 400);
line(200, 0, 200, 600);
line(400, 0, 400, 600);
}
void DrawPiece()//绘制棋子
{
for(size_t i=0;i<3;i++)
for (size_t j = 0; j < 3; j++)
{
switch (board_data[i][j])
{
case 'O':
circle(j* 200 + 100, i * 200 + 100, 67);
break;
case 'X':
line(j * 200+50, i * 200+50, (j + 1) * 200-50, (i + 1) * 200-50);
line((j+1)*200-50, 200*i+50,j*200+50, (i+1)*200-50);
break;
case'-':
break;
}
}
}
void DrawTipText()//绘制提示信息
{
static TCHAR str[64];
_stprintf_s(str, _T("当前棋子类型:%c"), current_piece);//和printf(“%c”,c)很像
settextcolor(RGB(225, 175, 45));
outtextxy(0, 0, str);
}
int main()
{
DWORD start_time = GetTickCount();
initgraph(600, 600);
bool Running = true;
BeginBatchDraw();
while(Running)
{
//读取信息
ExMessage msg;
//处理信息
while (peekmessage(&msg))
{
if (msg.message == WM_LBUTTONDOWN)
{
int x = msg.x;
int y = msg.y;
int index_x = x / 200;
int index_y = y / 200;//将棋盘网格跟图形界面构建索引
//尝试落子
if (board_data[index_y][index_x] == '-')
{
board_data[index_y][index_x] = current_piece;
if (current_piece == 'O')
{
current_piece = 'X';
}
else current_piece = 'O';//实现棋子的轮换
}
}
}
//绘制图像
cleardevice();
DrawBoard();
DrawPiece();
DrawTipText();
FlushBatchDraw();
if (CheckWin('X'))//检测到游戏结束,进行弹窗
{
MessageBox(GetHWnd(), _T("X玩家获胜"), _T("游戏结束"), MB_OK);
//MEssageBox()
//Hwnd, 父窗口句柄,用于找到当前窗口
//Text, 提示内容
//caption 弹窗标题
//type 弹窗样式
Running = false;
}
else if (CheckWin('O'))
{
MessageBox(GetHWnd(), _T("O玩家获胜"), _T("游戏结束"), MB_OK);
Running = false;
}
else if (CheckDraw())
{
MessageBox(GetHWnd(), _T("平局"), _T("游戏结束"), MB_OK);
}
DWORD end_time = GetTickCount();
DWORD delta_time = end_time - start_time;//计算循环单次时间落差
if (delta_time < 1000 / 60)
{
Sleep(1000 / 60 - delta_time);//要点:使用GetTickCount()来计算循环开始和一次循环结束所需要的时间落差,如果要确保画面以60hz刷新,那每次循环的总时间就是1000/60
//如果实际循环小于1000/60,那么我们通过Sleep()函数延时剩下的时间,以达到优化CPU占用的作用
}
}
EndBatchDraw();
//释放数据
return 0;
}
实现步骤
基本框架:
- 读取信息
- 处理信息
- 绘制图像
- 释放数据
int main()
{
DWORD start_time = GetTickCount();
initgraph(600, 600);//绘制600*600窗口
bool Running = true;
BeginBatchDraw();
while(Running)//主循环
{
//读取信息
ExMessage msg;
//处理信息
while (peekmessage(&msg))
{
if (msg.message == WM_LBUTTONDOWN)
{
int x = msg.x;
int y = msg.y;
int index_x = x / 200;
int index_y = y / 200;//将棋盘网格跟图形界面构建索引
//尝试落子
if (board_data[index_y][index_x] == '-')
{
board_data[index_y][index_x] = current_piece;
if (current_piece == 'O')
{
current_piece = 'X';
}
else current_piece = 'O';//实现棋子的轮换
}
}
}
//绘制图像
cleardevice();
DrawBoard();
DrawPiece();
DrawTipText();
FlushBatchDraw();
if (CheckWin('X'))//检测到游戏结束,进行弹窗
{
MessageBox(GetHWnd(), _T("X玩家获胜"), _T("游戏结束"), MB_OK);
//MEssageBox()
//Hwnd, 父窗口句柄,用于找到当前窗口
//Text, 提示内容
//caption 弹窗标题
//type 弹窗样式
Running = false;
}
else if (CheckWin('O'))
{
MessageBox(GetHWnd(), _T("O玩家获胜"), _T("游戏结束"), MB_OK);
Running = false;
}
else if (CheckDraw())
{
MessageBox(GetHWnd(), _T("平局"), _T("游戏结束"), MB_OK);
}
DWORD end_time = GetTickCount();
DWORD delta_time = end_time - start_time;//计算循环单次时间落差
if (delta_time < 1000 / 60)
{
Sleep(1000 / 60 - delta_time);//要点:使用GetTickCount()来计算循环开始和一次循环结束所需要的时间落差,如果要确保画面以60hz刷新,那每次循环的总时间就是1000/60
//如果实际循环小于1000/60,那么我们通过Sleep()函数延时剩下的时间,以达到优化CPU占用的作用
}
}
EndBatchDraw();
//释放数据
return 0;
}
要点知识
BeginBatchDraw();//双缓冲
FlushBatchDraw();
EndBatchDraw();
//对CPU占用进行优化:
//函数Sleep()
//由于while循环速度很快,但是我们不需要这么快速的刷新速度,那么使用Sleep函数进行休眠
//具体实现如下:
//利用GetTickCount()函数计算一次循环需要的时间
DWORD begin_time = GetTickCount();
DWORD end_time=GetTickCount();
DWORD delta_time= end_time-begin_time;
//如果循环所需要的时间小于60hz刷新所需要的时间也就是1000/60ms,那么休眠1000/60-delta_time 的时间
if(delta_time < 1000/60)
{
Sleep(1000/60-delta_time);
}
void DrawTipText()//绘制提示信息
{
static TCHAR str[64];
_stprintf_s(str, _T("当前棋子类型:%c"), current_piece);//和printf(“%c”,c)很像
settextcolor(RGB(225, 175, 45));
outtextxy(0, 0, str);
}