引言:GobangGame

这是一个使用纯Win32 SDK和C语言实现的五子棋游戏

在这个游戏中实现的功能

  • [x] 绘制一个15 * 15的棋盘

  • [x] 绘制5个着重点位置

  • [x] 根据鼠标左键的点击,可以绘制出黑色棋子;根据鼠标右键的点击,可以绘制出白色棋子

  • [x] 根据鼠标中键的点击,可以初始化棋盘

  • [x] 根据鼠标点击的实际位置,可以计算转化为临近点最近的那个点,在这个点上绘制棋子

  • [x] 当鼠标位置不在棋盘内,可以显示提示信息

  • [x] 五子棋判胜逻辑的实现

这个游戏还是算比较简单的,主要难点在于两点

  • 如何将鼠标点击的实际坐标,转化为临近最近的点显示棋子
  • 如何实现五子棋的判胜逻辑

如何根据鼠标点击的实际坐标,转为临近最近的点呢

这个实现是非常简单的,大家初中肯定都学过勾三股四弦五,就是勾股定理啦。我们只要计算当前实际点到它临近四个点的实际距离,然后拿到距离最短的那个点的逻辑位置就行啦。

这里的实现比较简单,因为代码大家也是可以拿到的,这里就不再赘述,直接贴上最关键的实现代码。

// 将实际坐标转化为逻辑坐标,这里需要进行实际点到棋盘点的转化
HRESULT _ExChangeLogicalPosition(POINT actualPostion, POINT ptLeftTop, int cxClient, int cyClient, POINT *logicalPostion)
{// 获得一小格的宽度和高度int cxCell = 0, cyCell = 0;_GetCellWidthAndHeight(ptLeftTop, cxClient, cyClient, &cxCell, &cyCell);// 检查点击有效性if (actualPostion.x < ptLeftTop.x || actualPostion.x > ptLeftTop.x + BOARD_CELL_NUM * cxCell ||actualPostion.y < ptLeftTop.y || actualPostion.y > ptLeftTop.y + BOARD_CELL_NUM * cyCell) {MessageBox(NULL ,TEXT("请点击棋盘内下棋!"), TEXT("提示"), MB_OK);return S_FALSE;}// 获取相邻四个点int xCount = 0, yCount = 0;POINT sidePoints[4] = { 0 };for (int x = ptLeftTop.x; x <= ptLeftTop.x + BOARD_CELL_NUM * cxCell; x += cxCell, xCount++) {if (actualPostion.x >= x && actualPostion.x <= x + cxCell) {sidePoints[0].x = x;sidePoints[2].x = x;sidePoints[1].x = x + cxCell;sidePoints[3].x = x + cxCell;break;}}for (int y = ptLeftTop.y; y <= ptLeftTop.y + BOARD_CELL_NUM * cyCell; y += cyCell, yCount++) {if (actualPostion.y >= y && actualPostion.y <= y + cyCell) {sidePoints[0].y = y;sidePoints[1].y = y;sidePoints[2].y = y + cyCell;sidePoints[3].y = y + cyCell;break;}}// 计算当前点到四个点到当前点距离double lengthCount[4] = { 0 };for (int item = 0; item < 4; ++item) {lengthCount[item] = pow(abs(sidePoints[item].x - actualPostion.x), 2) + pow(abs(sidePoints[item].y - actualPostion.y), 2);}// 获取四个距离值中最短的一个int shortestIndex = 0;for (int item = 0; item < 4; ++item) {if (lengthCount[item] < lengthCount[shortestIndex]) {shortestIndex = item;}}// 计算逻辑坐标,其中下标为0的点为基准点if (1 == shortestIndex) {xCount += 1;} else if (2 == shortestIndex) {yCount += 1;}else if (3 == shortestIndex) {xCount += 1;yCount += 1;}logicalPostion->x = xCount;logicalPostion->y = yCount;return S_OK;
}

如何实现五子棋的判胜逻辑

这是这个游戏的最难的一点,这一点也确实让我思考了很久。

思路是慢慢展开的,胜利的方式有三种,一种是横着连续5个棋子,一种是竖着连续5个棋子,另一种呢,就是斜着5个棋子。这里就需要对于坐标进行一些计算了。但是这里要记录同一类棋子同一方向的个数…

再按照上述的思考方式来考虑这个问题,就会越来越难了,那么怎么解决这个问题呢?

我想到了大一下学期学的数据结构,最长路径算法!对了,我们只要能让这个棋盘中,同一类棋子的最长路径为5就可以判定胜利啦!

这样就简化了问题,渐渐地,在这个主要思想的指导下,我又考虑到了一个棋子能判定胜利的方向有8个方向,我们判定胜利都是在这8个方向下遍历判断的。

遍历8个方向的时候,每个方向的棋子个数怎么计算呢?

这个其实也比较简单,使用递归!我们计算以一个基准点同一方向开始判定此此基准点的下一个点是不是同类棋子,如果是的话,则重复这个函数,如果不是的话,则返回计数。

我们拿到了每个棋子的计数,只要有一个棋子的技术等于了5,我们就可以判定此类棋子代表的那方胜利!很简单吧。

逻辑分析了这么久,其实还不如一个简单的总结简洁,这里整理如下:

  1. 遍历当前棋盘,传入一个基准点参数
  2. 遍历8个方向,传入一个方向值
  3. 根据方向值计算出下个点的坐标,与基准点比较,判断是否是同类棋子
  4. 如果是同类棋子,重复第3步;否则,返回计数
  5. 查看返回的计数是否等于5,如果等于5则判定该类棋子胜利

这里附上我觉得最为精华的一个递归函数,其他代码感兴趣的同学可以参看github拿到源代码,就不再赘述:

// 计算当前方向过去的同类棋子的个数
HRESULT _CountSameDiretionPointsNumber(int chessPoints[BOARD_CELL_NUM + 1][BOARD_CELL_NUM + 1], POINT point, Win_Direction direction, int *count)
{(*count) += 1;BOOLEAN bSame = FALSE;POINT movedPoint = {point.x, point.y};_IsSidewardHasSamePoint(chessPoints, point, direction, &bSame, &movedPoint);if (bSame == TRUE) {bSame = FALSE;POINT movedmovedPoint = { movedPoint.x, movedPoint.y };_CountSameDiretionPointsNumber(chessPoints, movedPoint, direction, count);}return S_OK;
}

总结

这个游戏的完成,花了我两个晚上。其中第一个晚上,主要用来绘制棋盘,绘制棋子,绘制辅助点,完成大体框架;第二个晚上,主要解决五子棋的判胜逻辑的实现。

总的来说,这个游戏中,我觉得还是算法最难。其他的都是多练可以提升的,不过是SDK函数的熟悉而已,而算法才是最练人的。希望自己再接再厉,在学习提升自己的编程熟练度的同时,也要加强算法的学习。

最后,为想要拿到源码参考的同学们附上项目的代码地址这是一个使用纯Win32 SDK和C语言实现的五子棋游戏,因为本人水平有限,定有许多不足之处,也请各位不吝赐教。

一个使用纯Win32 SDK和C语言实现的五子棋游戏相关推荐

  1. 用c语言做一个五子棋程序,C语言制作简单五子棋游戏

    原标题:C语言制作简单五子棋游戏 C语言制作简单的五子棋游戏 学习C语言的人很多,但是用C语言很少,而用来为自己所用,来做游戏的人就更少了,很多人都是跟着学校学习,学校讲到哪就坐到哪,但是以后却还是不 ...

  2. c语言带坐标五子棋代码复制,C语言编写的五子棋游戏源代码

    已结贴√ 问题点数:20 回复次数:28 C语言编写的五子棋游戏源代码 # include # include # include # include//插入输入输出头文件 # include//字符 ...

  3. 如何用C语言来实现——五子棋游戏

    每天进步一点点,坚持带来大改变!!! 目录 前言: 实现思路: 1.代码搭建: 2.框架搭建: 3.游戏功能实现: 1.创建棋盘并用空格初始化: 2.打印棋盘: 3.玩家下棋: 4.电脑下棋: 5.判 ...

  4. 纯 Win32 SDK程序为什么每次要获取设备描述表句柄

    做过Win32 API程序的就会发现,要对窗口输出时,每次都要获取设备描述表句柄:都是对同一个窗口输出,设备描述表是一个:为什么每次都要获取设备描述表句柄呢?获取一次行吗? 做一个Win32 API程 ...

  5. 简单五子棋游戏c语言简单,C语言制作简单五子棋游戏

    #pragma comment(lib,'winmm.lib') //玩游戏 void PlayGame() { //鼠标操作 int chess[N][N] = { 0 };//标志没有棋子的标志 ...

  6. Leo-io 的C语言实现简单五子棋游戏观后感

    源代码: /************************************************************** ** 文 件 名:wuziqi.cpp ** 功    能:扫 ...

  7. 【全网最强C语言学习】五子棋游戏

    目录 一.前言 二.头文件 三.menu菜单函数 四.初始化棋盘Initboard函数 五.显示棋盘Displayboard函数 六.落子函数 七.判断输赢ifwin 八.人机.人人模式的选择 九.作 ...

  8. vc6.0c语言五子棋程序,哪位大虾可以给我个VC6.0下用C语言编的五子棋,要有流程图...

    五子棋 代码 VC6.0 qq_29018467112015-06-14 五子棋 (用C语言编写五子棋游戏) rannianzhixia170392017-04-20 基于easyx图形的五子棋游戏 ...

  9. c语言五子棋开题报告,基于VC的五子棋游戏的设计与实现(附答辩记录)

    基于VC的五子棋游戏的设计与实现(附答辩记录)(包含选题审批表,任务书,开题报告,中期检查报告,毕业论文12300字,程序) 摘 要:以计算机技术和网络技术为核心的现代网络技术已在现实生活和生产中得以 ...

最新文章

  1. Gradle For Android
  2. java自带工具_深入了解Java JDK自带工具,包括javac、jar、jstack等,实用~
  3. 波束形成、回声消除、声源定位及端到端等语音信号处理算法
  4. python3 字符串方法
  5. js/css文件修改后浏览器本地缓存解决
  6. org.jeecgframework.core.common.exception.MyExceptionHandler]java.lang.NullPointerException
  7. javascript基础系列:数组常用方法解析
  8. presto 设置mysql连接,Apache Presto配置设置
  9. Oracle 11g中关于数据定义的思考
  10. 9600kf功耗和温度评测_谁更受主流消费者青睐:AMD锐龙5 3500X对比英特尔酷睿i5-9600KF...
  11. Android——手机系统重装的备忘笔记
  12. 关闭VMware声音
  13. 凸优化有关的数值线性代数知识一:矩阵结构与算法复杂性
  14. lamp 测试mysql_搭建LAMP测试环境
  15. drozer could not find java_Drozer-Android安全测试
  16. 企业网络项目投标范文
  17. 数据库表结构及索引设计
  18. 基于颜色的R2V软件快速矢量化
  19. MATLAB 中如何使用 help
  20. ZYNQ芯片软硬件协同开发二:最简Linux操作系统的硬件部分设计

热门文章

  1. 怎么批量查询快递物流信息
  2. 柠萌影业三次冲刺IPO,爆款制造机的压力大爆了
  3. 我叫MongoDb,不懂我的看完我的故事您就入门啦!
  4. 金茂服务香港上市破发:大跌29% 公司市值52亿港元
  5. 前端学习(三)UI设计
  6. UE4如何使用Left Shift+W增加移动速度
  7. 幼儿园教师怎么教计算机知识,幼儿园教师的专业知识到底包含哪些,家长必知!...
  8. xctf 攻防世界 MISC
  9. 上火有多种 “灭火”要对症
  10. 图像跟踪(1) CSK