失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > 使用EasyX实现简单的五子棋双人对战

使用EasyX实现简单的五子棋双人对战

时间:2021-06-26 23:12:39

相关推荐

使用EasyX实现简单的五子棋双人对战

基于Visual Stdio IDE,利用EasyX图形函数库工具搭建可视化图形操作界面。通过鼠标在图形界面上点击选子,实现了五子棋的双人对战小游戏。

本程序主体框架是从/ArchyLi/article/details/70446314学习来的,但其功能简单、界面简陋、程序功能还有漏洞,于是做出了一下修改。

添加功能:1.增加随时退出功能、2.增加重新开始功能、3.增加悔棋功能 4.增加总比分显示、5.增加落子提示

美化界面:从开始界面,游戏界面、到结束界面使用一些网上搜集来的图片作为背景,不再是黑白背景

修复漏洞及优化:1.修复了继续游戏时采用层层递归可能导致栈溢出的潜在问题、2.优化了判定胜利规则程序,不再是整个棋盘遍历。

2.效果展示

开始界面

正式游戏界面

结束界面

3.程序代码

采用的是C的面向过程的编程思想,以后会考虑改成C++面向对象的编程结构。关于字符集设置网上很多说设置成“多字节字符集”,但我的还是乱码。于是我将字符集设置成了“未设置”,字体就不乱码了。

#include<graphics.h>#include<conio.h>#include<windows.h>#include<stdio.h>#include<string>#include <time.h>#define GridSize 15#define InternalSize 33using namespace std;#pragma warning(disable:4996)void menu();bool play();void display();bool playgame();bool IsAgain(int index);void DisplayExitGameMessage();bool IsWin(int i, int j, int player);int a[GridSize][GridSize] = { 0 };//棋盘标记场IMAGE img_bk1, img_bk2;int Player1WinCount = 0, Player2WinCount = 0;int main(){//initgraph(600, 600, SHOWCONSOLE);initgraph(600, 600);menu();DisplayExitGameMessage();closegraph();return 0;}void menu(){IMAGE img;setaspectratio(1.1f, 1);//loadimage(&img, (LPCTSTR)"IMAGE", (LPCTSTR)"tur", 0, 0, true);loadimage(&img, _T(".\\五子棋1.jpg"));putimage(0, 0, &img, SRCPAINT);settextstyle(50, 20, (LPCTSTR)"楷体");settextcolor(YELLOW);setbkmode(WHITE);outtextxy(150, 100, (LPCTSTR)"五子棋双人对战");outtextxy(200, 400, (LPCTSTR)"开始游戏");outtextxy(200, 451, (LPCTSTR)"退出游戏");MOUSEMSG m;while (true){m = GetMouseMsg();if (m.uMsg == WM_MOUSEMOVE && m.x >= 200 && m.x <= 360 && m.y >= 400 && m.y <= 450)//判断鼠标是否移动到了开始游戏,是则用黄色方框标记{setlinecolor(YELLOW);rectangle(200, 400, 360, 450);}else {setlinecolor(getbkcolor());rectangle(200, 400, 360, 450);}if (m.uMsg == WM_MOUSEMOVE && m.x >= 200 && m.x <= 360 && m.y >= 451 && m.y <= 500)//判断鼠标是否移动到了退出游戏,是则用黄色方框标记{setlinecolor(YELLOW);rectangle(200, 451, 360, 500);}else {setlinecolor(getbkcolor());rectangle(200, 451, 360, 500);}if (m.uMsg == WM_LBUTTONDOWN && m.x >= 200 && m.x <= 360 && m.y >= 400 && m.y <= 450)//判断是否点击开始游戏{cleardevice();Sleep(200);bool Continue_Game = true;while (Continue_Game) {Continue_Game = play();//开始游戏并循环判断是否继续游戏}break;}if (m.uMsg == WM_LBUTTONDOWN && m.x >= 200 && m.x <= 360 && m.y >= 451 && m.y <= 500)//判断是否点击退出游戏{break;}}}bool play(){cleardevice();graphdefaults();display();//显示背景棋盘setlinecolor(WHITE);settextstyle(20, 10, (LPCTSTR)"楷体");settextcolor(BLACK);setbkmode(WHITE);outtextxy(5, 5, (LPCTSTR)"player1:黑子");outtextxy(5, 28, (LPCTSTR)"步数: ");outtextxy(475, 5, (LPCTSTR)"player2:白子");outtextxy(475, 28, (LPCTSTR) "步数: ");settextstyle(25, 15, (LPCTSTR)"楷体");//高25个像素,宽15个像素outtextxy(475, 560, (LPCTSTR) "退出游戏");outtextxy(10, 560, (LPCTSTR) "重新开始");outtextxy(270, 560, (LPCTSTR) "悔棋");return playgame();}void display()//显示棋盘网格{loadimage(&img_bk1, _T(".\\水墨画.jpg"));putimage(0, 0, &img_bk1, SRCPAINT);clearrectangle(50, 50, 550, 550);loadimage(&img_bk2, _T(".\\五子棋棋盘.jpg"));putimage(50, 50, &img_bk2, SRCPAINT);}bool playgame()//正式开始游戏{settextstyle(25, 15, (LPCTSTR)"楷体");//高25个像素,宽15个像素string str = to_string(Player1WinCount) + " : " + to_string(Player2WinCount);outtextxy(265, 15, (LPCTSTR)str.data());int StepNum1 = 0, StepNum2 = 0;settextstyle(20, 10, (LPCTSTR)"楷体");outtextxy(60, 27, (LPCTSTR)to_string(StepNum1).data());outtextxy(530, 27, (LPCTSTR)to_string(StepNum2).data());settextstyle(25, 15, (LPCTSTR)"楷体", 2700, 0, 0, 0, 0, 0);//高25个像素,宽15个像素outtextxy(25, 50, (LPCTSTR)"黑方落子");memset(a, 0, sizeof(a));int Pre_i = -1, Pre_j = -1, Pre_C = -1, Pre_R = -1;int player = 1; bool UndoAble = true;MOUSEMSG msg;while (true){msg = GetMouseMsg();//“退出游戏”区域相关操作if (msg.uMsg == WM_MOUSEMOVE && msg.x >= 475 && msg.x <= 595 && msg.y >= 560 && msg.y <= 585)//判断鼠标是否移动到了退出游戏,是则用黄色方框标记{setlinecolor(YELLOW);rectangle(475, 560, 595, 585);}else {setlinecolor(BLACK);rectangle(475, 560, 595, 585);}if (msg.uMsg == WM_LBUTTONDOWN && msg.x >= 460 && msg.x <= 580 && msg.y >= 550 && msg.y <= 575)//判断鼠标是否点击了退出游戏{return false;}//“重新开始”区域相关操作if (msg.uMsg == WM_MOUSEMOVE && msg.x >= 10 && msg.x <= 130 && msg.y >= 560 && msg.y <= 585)//判断鼠标是否移动到了退出游戏,是则用黄色方框标记{setlinecolor(YELLOW);rectangle(10, 560, 130, 585);}else {setlinecolor(BLACK);rectangle(10, 560, 130, 585);}if (msg.uMsg == WM_LBUTTONDOWN && msg.x >= 10 && msg.x <= 130 && msg.y >= 560 && msg.y <= 585)//判断鼠标是否点击了退出游戏{Player1WinCount = 0, Player2WinCount = 0;return true;}//“悔棋”区域相关操作if (msg.uMsg == WM_MOUSEMOVE && msg.x >= 270 && msg.x <= 330 && msg.y >= 560 && msg.y <= 585)//判断鼠标是否移动到了悔棋,是则用黄色方框标记{setlinecolor(YELLOW);rectangle(270, 560, 330, 585);}else {setlinecolor(BLACK);rectangle(270, 560, 330, 585);}if (msg.uMsg == WM_LBUTTONDOWN && msg.x >= 270 && msg.x <= 330 && msg.y >= 560 && msg.y <= 585)//判断鼠标是否点击了悔棋{HWND hq = FindWindow(NULL, "五子棋双人对战");//获取父窗口句柄if (Pre_i == -1) {MessageBox(hq, (LPCTSTR) "目前还不能悔棋", "提示", MB_OK);}else if (UndoAble) {UndoAble = false;a[Pre_i][Pre_j] = 0;clearcircle(Pre_C, Pre_R, 12);putimage(Pre_C - 12, Pre_R - 12, 25, 25, &img_bk2, Pre_C - 12 - 50, Pre_R - 12 - 50, SRCCOPY);if (player == 1) {settextstyle(20, 10, (LPCTSTR)"楷体");putimage(530, 27, 20, 20, &img_bk1, 530, 27, SRCCOPY);outtextxy(530, 27, (LPCTSTR)to_string(--StepNum2).data());settextstyle(25, 15, (LPCTSTR)"楷体", 2700, 0, 0, 0, 0, 0);//高25个像素,宽15个像素outtextxy(575, 50, (LPCTSTR)"白方落子");settextstyle(25, 15, (LPCTSTR)"楷体", 0, 0, 0, 0, 0, 0);//高25个像素,宽15个像素clearrectangle(10, 70, 40, 150);putimage(10, 70, 30 + 1, 100 + 1, &img_bk1, 10, 70, SRCCOPY);player = 2;}else {settextstyle(20, 10, (LPCTSTR)"楷体");putimage(60, 27, 20, 20, &img_bk1, 60, 27, SRCCOPY);outtextxy(60, 27, (LPCTSTR)to_string(--StepNum1).data());settextstyle(25, 15, (LPCTSTR)"楷体", 2700, 0, 0, 0, 0, 0);//高25个像素,宽15个像素outtextxy(25, 50, (LPCTSTR)"黑方落子");settextstyle(25, 15, (LPCTSTR)"楷体", 0, 0, 0, 0, 0, 0);//高25个像素,宽15个像素clearrectangle(560, 70, 590, 150);putimage(560, 70, 30 + 1, 100 + 1, &img_bk1, 560, 70, SRCCOPY);player = 1;}}else {MessageBox(hq, (LPCTSTR) "最多连续悔一次", "已经悔过棋了", MB_OK);}}//棋盘区域点击操作if (msg.uMsg == WM_LBUTTONDOWN){int i = 0, j = 0;for (int column = 71; j < GridSize; j++, j % 2 == 0 ? column += InternalSize : column += InternalSize - 1){if (msg.x <= column + 10 && msg.x >= column - 10)//检测鼠标点击所在列{for (int row = 70; i < GridSize; i++, i % 2 == 0 ? row += InternalSize : row += InternalSize - 1){if (msg.y <= row + 10 && msg.y >= row - 10)//检测鼠标点击所在行{Pre_i = i; Pre_j = j; UndoAble = true;Pre_C = column; Pre_R = row;if (player == 1 && a[i][j] == 0){setfillcolor(BLACK);solidcircle(column, row, 12);a[i][j] = 1;settextstyle(20, 10, (LPCTSTR)"楷体" ,0, 0, 0, 0, 0, 0);putimage(60, 27, 20, 20, &img_bk1, 60, 27, SRCCOPY);outtextxy(60, 27, (LPCTSTR)to_string(++StepNum1).data());settextstyle(25, 15, (LPCTSTR)"楷体", 2700, 0, 0, 0, 0, 0);//高25个像素,宽15个像素outtextxy(575, 50, (LPCTSTR)"白方落子");settextstyle(25, 15, (LPCTSTR)"楷体", 0, 0, 0, 0, 0, 0);//高25个像素,宽15个像素clearrectangle(10, 70, 40, 150);putimage(10, 70, 30+1, 100+1, &img_bk1, 10, 70, SRCCOPY);if (IsWin(i, j, 1)) {settextstyle(25, 15, (LPCTSTR)"楷体");//高25个像素,宽15个像素putimage(265, 15, 75, 25, &img_bk1, 265, 15, SRCCOPY);str = to_string(++Player1WinCount) + " : " + to_string(Player2WinCount);outtextxy(265, 15, (LPCTSTR)str.data());return IsAgain(1);//判断是否赢及是否继续玩}player = 2;break;}else if (player == 2 && a[i][j] == 0){setfillcolor(WHITE);solidcircle(column, row, 12);a[i][j] = 2;settextstyle(20, 10, (LPCTSTR)"楷体", 0, 0, 0, 0, 0, 0);putimage(530, 27, 20, 20, &img_bk1, 530, 27, SRCCOPY);outtextxy(530, 27, (LPCTSTR)to_string(++StepNum2).data());settextstyle(25, 15, (LPCTSTR)"楷体", 2700, 0, 0, 0, 0, 0);//高25个像素,宽15个像素outtextxy(25, 50, (LPCTSTR)"黑方落子");settextstyle(25, 15, (LPCTSTR)"楷体", 0, 0, 0, 0, 0, 0);//高25个像素,宽15个像素clearrectangle(560, 70, 590, 150);putimage(560, 70, 30+1, 100+1, &img_bk1, 560, 70, SRCCOPY);if (IsWin(i, j, 2)) {settextstyle(25, 15, (LPCTSTR)"楷体");//高25个像素,宽15个像素putimage(265, 15, 75, 25, &img_bk1, 265, 15, SRCCOPY);str = to_string(Player1WinCount) + " : " + to_string(++Player2WinCount);outtextxy(265, 15, (LPCTSTR)str.data());return IsAgain(2);//判断是否赢及是否继续玩}player = 1;break;}}}break;}}}}}bool IsWin(int i, int j, int player) {int count = 1;//判断纵向是否有五子连珠for (int index_i = i - 1, index_j = j; index_i >= 0 && a[index_i][index_j] == player; index_i--) count++;for (int index_i = i + 1, index_j = j; index_i < GridSize && a[index_i][index_j] == player; index_i++) count++;if (count >= 5) return true;else count = 1;//判断横向是否有五子连珠for (int index_i = i, index_j = j - 1; index_j >= 0 && a[index_i][index_j] == player; index_j--) count++;for (int index_i = i, index_j = j + 1; index_j < GridSize && a[index_i][index_j] == player; index_j++) count++;if (count >= 5) return true;else count = 1;//判断135度斜轴是否有五子连珠for (int index_i = i - 1, index_j = j - 1; index_i >= 0 && index_j >= 0 && a[index_i][index_j] == player; index_i--, index_j--) count++;for (int index_i = i + 1, index_j = j + 1; index_i < GridSize && index_j < GridSize&& a[index_i][index_j] == player; index_i++, index_j++) count++;if (count >= 5) return true;else count = 1;//判断45度斜轴是否有五子连珠for (int index_i = i - 1, index_j = j + 1; index_i >= 0 && index_j < GridSize && a[index_i][index_j] == player; index_i--, index_j++) count++;for (int index_i = i + 1, index_j = j - 1; index_i < GridSize && index_j >= 0 && a[index_i][index_j] == player; index_i++, index_j--) count++;if (count >= 5) return true;else count = 1;return false;}bool IsAgain(int index){settextstyle(20, 10, (LPCTSTR)"楷体");settextcolor(YELLOW);if (index == 1) {outtextxy(250, 50, (LPCTSTR) "player1 win!");}else {outtextxy(250, 50, (LPCTSTR) "player2 win!");}HWND hq = FindWindow(NULL, "五子棋双人对战");//获取父窗口句柄string str = "Player" + to_string(index) + " Win";int quit = MessageBox(hq, (LPCTSTR) "是否继续游戏", (LPCTSTR)str.data(), MB_YESNO);if (IDYES == quit) return true;else return false;}void DisplayExitGameMessage() {cleardevice();IMAGE img;loadimage(&img, _T(".\\水墨画2.jpg"));putimage(0, 0, &img, SRCPAINT);settextcolor(BLACK);settextstyle(50, 20, (LPCTSTR)"楷体");outtextxy(160, 80, (LPCTSTR)"欢迎下次再来!");Sleep(1500);}

4.问题与不足

待解决的问题:1.没有实现人机对战功能、2.不能两台电脑之间通信对战。

不足:1.程序比较冗余(需优化) 、2.变量管理复杂,经常遇到改一个变量要多处手动修改

5.附录图片

程序中用到的背景图图片直接跟源文件放到同一目录下即可

水墨画

水墨画2

五子棋1

五子棋棋盘

如果觉得《使用EasyX实现简单的五子棋双人对战》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。