基于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实现简单的五子棋双人对战相关推荐

  1. 五子棋双人对战c语言课程设计,五子棋(双人对战) C语言课程设计.doc

    五子棋(双人对战) C语言课程设计 C语言程序设计 题 目 五子棋(双人对战) 指导教师 曹东燕 学生姓名 夏文龙 于文杰 邢健 学 号 201000802032 201000802114 20100 ...

  2. Scratch3.0——助力新进程序员理解程序(难度案例三、五子棋双人对战-电脑需要AI写不出来)

    Scratch3.0--助力新进程序员理解程序(难度案例三.五子棋双人对战-电脑需要AI写不出来) 前言 一般来说,针对6-18岁的少年儿童开展的编程教育,现在,最常见的形式是线上和线下模式相结合的课 ...

  3. c语言课程设计作业五子棋,C语言课程设计-五子棋双人对战程序

    C语言课程设计-五子棋双人对战程序 C语言课程设计-五子棋双人对战程序|c语言程序代码编程小程序设计|c语言课程设计报告课程案例 /*      本程序在Turbo C或Borland C下编译通过  ...

  4. 五子棋双人对战的实现

    完成了界面,实现双人对战就很简单了. 1.定义公共变量和结构变量 Public Structure FivePos Dim x As Integer Dim y As Integer Dim colo ...

  5. C++ 五子棋双人对战免费源码----鼠标操作(DEV-CPP)

    五子棋的规则就不用我说了吧,大家应该都玩过 今天,我来发一个鼠标操作的 函数使用须知 首先最重要的是这个函数: 头文件:windows.h 注意:请先将窗口属性调为插入模式(方便用这个函数): 1.右 ...

  6. python五子棋人人对战_简单的五子棋-人人对战

    1新建工程 项目->VC++->MFC->MFC应用程序->输入名称->单文档->Window套接字->完成 2资源编辑 视图->其他窗口->资源 ...

  7. 基于SpringBoot+MyBatis 五子棋双人对战

    1. 核心功能 2. 演示效果 3. 创建项目 4. 数据库设计 5. 配置文件 6. 用户模块 6.1 登录实现 6.1.1 前后端交互接口 6.1.2 model 层 6.1.3 mapper 层 ...

  8. c语言五子棋双人对战,tc 版双人对战的五子棋

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 map[i][j]=0; cleardevice(); setbkcolor(13); setcolor(1); setfillstyle(1,2); s ...

  9. C# winform 简单五子棋 200行代码实现双人对战

    1.需求 基于C# winform用200行代码实现简易五子棋双人对战,支持悔棋,需要的知识有C# winform界面,C#,以及几张素材图片. 2.界面 界面设计如图1所示,背影图是用Graphic ...

最新文章

  1. 数据结构与算法分析——C语言描述
  2. 雅虎成立特别委员会评估新战略选项
  3. 职高中专的模块化课程设计难点
  4. 在Metro App中显示Toast notification
  5. 聊个天就把生信分析做了?你的未来在哪里?
  6. fiddler汉化版可以改成英文吗_可以把推拉门改成平开窗吗?推拉门和平开窗哪个更好?...
  7. 自定义WPF ListBox的选择样式
  8. 从程序员到项目经理(四):外行可以领导内行吗
  9. android数据存放map_Android存储数据到本地文件
  10. MongoDB小结26 - 地理空间索引
  11. SLF4J介绍以及与LOG4J、LOG4J2、LOGBACK整合方法
  12. 老司机带你用python爬取妹子图,接稳这波福利
  13. oracle mysql 同义词_Oracle数据库同义词
  14. 蜗牛星际 完美安装 ESXI6.7 全面教程(一)
  15. yolov5 代码内容解析
  16. 手用计算机电池,二手电脑器材中的电池问题
  17. 【机器学习笔记】如何改进算法性能
  18. 编程题 进制转换(Java实现)
  19. 聊一聊 JavaScript 的一些奇葩知识
  20. vue项目中使用bimface

热门文章

  1. Mapreduce程序 统计文件中每个单词出现次数
  2. 北京小中介的租房到底有多坑?
  3. 使用URLConnection爬取评论
  4. Java计算抛物线轨迹
  5. 无任何网络提供程序接受指定的网络路径”问题的几个解决方法
  6. 宝塔面板安装和创建网站/必看教程
  7. 各种安装包打包发布工具(安装制作工具)评测
  8. 通往编程高手之路:《深入理解操作系统》
  9. 卸载Symantec Endpoint Protection, 无需密码的卸载方法
  10. Dou学网-影视号起号视频教程