使用EasyX实现简单的五子棋双人对战
基于Visual Stdio 2017 IDE,利用EasyX图形函数库工具搭建可视化图形操作界面。通过鼠标在图形界面上点击选子,实现了五子棋的双人对战小游戏。
本程序主体框架是从https://blog.csdn.net/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 33
using 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实现简单的五子棋双人对战相关推荐
- 五子棋双人对战c语言课程设计,五子棋(双人对战) C语言课程设计.doc
五子棋(双人对战) C语言课程设计 C语言程序设计 题 目 五子棋(双人对战) 指导教师 曹东燕 学生姓名 夏文龙 于文杰 邢健 学 号 201000802032 201000802114 20100 ...
- Scratch3.0——助力新进程序员理解程序(难度案例三、五子棋双人对战-电脑需要AI写不出来)
Scratch3.0--助力新进程序员理解程序(难度案例三.五子棋双人对战-电脑需要AI写不出来) 前言 一般来说,针对6-18岁的少年儿童开展的编程教育,现在,最常见的形式是线上和线下模式相结合的课 ...
- c语言课程设计作业五子棋,C语言课程设计-五子棋双人对战程序
C语言课程设计-五子棋双人对战程序 C语言课程设计-五子棋双人对战程序|c语言程序代码编程小程序设计|c语言课程设计报告课程案例 /* 本程序在Turbo C或Borland C下编译通过 ...
- 五子棋双人对战的实现
完成了界面,实现双人对战就很简单了. 1.定义公共变量和结构变量 Public Structure FivePos Dim x As Integer Dim y As Integer Dim colo ...
- C++ 五子棋双人对战免费源码----鼠标操作(DEV-CPP)
五子棋的规则就不用我说了吧,大家应该都玩过 今天,我来发一个鼠标操作的 函数使用须知 首先最重要的是这个函数: 头文件:windows.h 注意:请先将窗口属性调为插入模式(方便用这个函数): 1.右 ...
- python五子棋人人对战_简单的五子棋-人人对战
1新建工程 项目->VC++->MFC->MFC应用程序->输入名称->单文档->Window套接字->完成 2资源编辑 视图->其他窗口->资源 ...
- 基于SpringBoot+MyBatis 五子棋双人对战
1. 核心功能 2. 演示效果 3. 创建项目 4. 数据库设计 5. 配置文件 6. 用户模块 6.1 登录实现 6.1.1 前后端交互接口 6.1.2 model 层 6.1.3 mapper 层 ...
- c语言五子棋双人对战,tc 版双人对战的五子棋
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 map[i][j]=0; cleardevice(); setbkcolor(13); setcolor(1); setfillstyle(1,2); s ...
- C# winform 简单五子棋 200行代码实现双人对战
1.需求 基于C# winform用200行代码实现简易五子棋双人对战,支持悔棋,需要的知识有C# winform界面,C#,以及几张素材图片. 2.界面 界面设计如图1所示,背影图是用Graphic ...
最新文章
- 数据结构与算法分析——C语言描述
- 雅虎成立特别委员会评估新战略选项
- 职高中专的模块化课程设计难点
- 在Metro App中显示Toast notification
- 聊个天就把生信分析做了?你的未来在哪里?
- fiddler汉化版可以改成英文吗_可以把推拉门改成平开窗吗?推拉门和平开窗哪个更好?...
- 自定义WPF ListBox的选择样式
- 从程序员到项目经理(四):外行可以领导内行吗
- android数据存放map_Android存储数据到本地文件
- MongoDB小结26 - 地理空间索引
- SLF4J介绍以及与LOG4J、LOG4J2、LOGBACK整合方法
- 老司机带你用python爬取妹子图,接稳这波福利
- oracle mysql 同义词_Oracle数据库同义词
- 蜗牛星际 完美安装 ESXI6.7 全面教程(一)
- yolov5 代码内容解析
- 手用计算机电池,二手电脑器材中的电池问题
- 【机器学习笔记】如何改进算法性能
- 编程题 进制转换(Java实现)
- 聊一聊 JavaScript 的一些奇葩知识
- vue项目中使用bimface