电脑象棋循序渐进(三):让电脑掌握象棋规则
与本文配套的示范程序是“象棋小巫师”0.2版,程序清单是: (1) XQWL02.CPP——C++源程序; (2) XQWLIGHT.RC——资源描述文件; (3) RESOURCE.H——资源符号定义文件; (4) RES目录——图标、图片、声音等资源。 在阅读本章前,建议读者先阅读象棋百科全书网计算机博弈专栏的以下几篇译文: (1) 国际象棋程序设计(一):引言(François Dominic Laramée); (2) 国际象棋程序设计(二):数据结构(François Dominic Laramée); (3) 国际象棋程序设计(三):着法的产生(François Dominic Laramée); (4) 数据结构——简介(Bruce Moreland); (5) 数据结构——0x88着法产生方法(Bruce Moreland)。 3.1 走法生成器 走法生成器是象棋程序中的一个重要组成部分,它可以解决几乎所有象棋规则的问题。 假设我们的棋盘使用9x10的数组,按照常规的做法,找到一个马的所有走法,这将是一件非常痛苦的事:
不仅代码数量庞大,运行速度缓慢,而且一不小心就容易写错。 好在我们的棋盘是一个大小为16x16的二维数组,只不过写在程序里的是 ucpcSquares[256] 而已。
00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 0a | 0b | 0c | 0d | 0e | 0f |
10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 1a | 1b | 1c | 1d | 1e | 1f |
20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 2a | 2b | 2c | 2d | 2e | 2f |
30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 3a | 3b | 3c | 3d | 3e | 3f |
40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 4a | 4b | 4c | 4d | 4e | 4f |
50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 5a | 5b | 5c | 5d | 5e | 5f |
60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 6a | 6b | 6c | 6d | 6e | 6f |
70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 7a | 7b | 7c | 7d | 7e | 7f |
80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 8a | 8b | 8c | 8d | 8e | 8f |
90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 9a | 9b | 9c | 9d | 9e | 9f |
a0 | a1 | a2 | a3 | a4 | a5 | a6 | a7 | a8 | a9 | aa | ab | ac | ad | ae | af |
b0 | b1 | b2 | b3 | b4 | b5 | b6 | b7 | b8 | b9 | ba | bb | bc | bd | be | bf |
c0 | c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c9 | ca | cb | cc | cd | ce | cf |
d0 | d1 | d2 | d3 | d4 | d5 | d6 | d7 | d8 | d9 | da | db | dc | dd | de | df |
e0 | e1 | e2 | e3 | e4 | e5 | e6 | e7 | e8 | e9 | ea | eb | ec | ed | ee | ef |
f0 | f1 | f2 | f3 | f4 | f5 | f6 | f7 | f8 | f9 | fa | fb | fc | fd | fe | ff |
- 上表就是9x10的象棋棋盘在16x16的数组中的位置,我们将在这个棋盘上演绎马是如何走棋的。 首先,我们预置一个常量数组 ccInBoard[256],表示哪些格子在棋盘外(紫色格子,填0),哪些格子在棋盘内(浅色格子,填1),所以就没有必要使用 x >= X_LEFT && x <= X_RIGHT && y >= Y_TOP && y <= Y_BOTTOM 之类的语句了,取而代之的是 ccInBoard[sq] != 0。 其次,一维数组的好就是上下左右关系非常简明——上面一格是 sq - 16,下面一格是 sq + 16,左面一格是 sq - 1,右面一格是 sq + 1。马可以跳的点只有8个,终点相对起点的偏移值是固定的:
- const char ccKnightDelta[4][2] = {{-33, -31}, {-18, 14}, {-14, 18}, {31, 33}};
- 而对应的马腿的偏移值是:
- const char ccKingDelta[4] = {-16, -1, 1, 16};
- 这个数组之所以命名为 ccKingDelta,是因为它也是帅(将)的偏移值。 这样,找到一个马的所有走法就容易很多了。首先判断某个方向上的马腿是否有子,然后判断该方向上的两个走法是否能走:
- for (i = 0; i < 4; i ++) {
- sqPin = sqSrc + ccKingDelta[i];
- if (IN_BOARD(sqPin) && ucpcSquares[sqPin] == 0) {
- for (j = 0; j < 2; j ++) {
- sqDst = sqSrc + ccKnightDelta[i][j];
- if (IN_BOARD(sqDst) && !SELF_PIECE(ucpcSquares[sqDst])) {
- ADD_MOVE(sqSrc, sqDst);
- }
- }
- }
- }
- 用类似的办法就可以产生其他棋子的所有走法。 3.2 判断走法是否符合规则 尽管我们已经使用了一些炫技,让走法生成器尽可能地小巧,但它仍然是象棋程序中最耗费时间的运算模块。有时候走法生成器真是大材小用了,比如用户点击鼠标走一步棋的时候,判断这步棋是否符合走法规则,就有几种不同的考虑: A. 用走法生成器产生全部走法,看看这些走法中有没有用户刚才走出的那步棋,如果没有就说明用户在乱走; B. 前一种做法中,大部分工作都是白费的,因为用户只是走了一个棋子,走法生成器没必要生成其他棋子的走法; C. 用户只走了一步棋,而走法生成器会生成一个棋子的所有走法,是不是太浪费了呢? 判断一个走法是否合理,有更简单的方法。依然以马为例,假设用户的鼠标动作肯定在棋盘内的,那么判断过程如下: (1) 马是否走了马步,即位移是否符合 ccKinghtDelta 中的值; (2) 根据马步,找到对应的马腿位置,判断马腿的格子上是否有棋子。 在象棋小巫师中,我们用了一个 KNIGHT_PIN(sqSrc, sqDst) 的函数来获取马腿的位置(如果函数返回 sqSrc,则说明不是马步)。这样,判断马的某个走法是否符合规则,只需要很简单的两句话:
- sqPin = KNIGHT_PIN(sqSrc, sqDst);
- return sqPin != sqSrc && ucpcSquares[sqPin] == 0;
-
3.3 判断将军 到现在为止,我们剩下一件事没有做了,那就是判断胜负。中国象棋的胜负标准就是帅(将)有没有被将死或困毙,我们的做法很简单——生成所有走法,如果走任意一步都会被将军,那么该局面就是将死或困毙的局面,棋局到此结束。 那么如何来判断是否被将军呢?我们有两种做法: A. 让对方生成全部走法,看看其中有没有走法可以吃掉自己的帅(将); B. 按照判断走法是否符合规则的思路,采用更简单的做法。 第一种做法没有什么不对的,但电脑象棋程序每秒种需要分析上万个局面,对每个局面都去生成全部走法显然太花时间了,所以我们要尝试第二种做法。其实判断帅(将)是否被将军的过程并不复杂: (1) 假设帅(将)是车,判断它是否能吃到对方的车和将(帅)(中国象棋中有将帅不能对脸的规则); (2) 假设帅(将)是炮,判断它是否能吃到对方的炮; (3) 假设帅(将)是马,判断它是否能吃到对方的马,需要注意的是,帅(将)的马腿用的数组是 ccAdvisorDelta,而不是 ccKingDelta; (4) 假设帅(将)是过河的兵(卒),判断它是否能吃到对方的卒(兵)。 这样,一个复杂的走法生成过程(方案A)就被简化成几个简单的走法判断过程(方案B)。
象棋小巫师示范程序(0.1~0.6)下载:http://www.elephantbase.net/download/xqwlight_win32.7z
CSDN下载频道:http://d.download.csdn.net/source/407014
电脑象棋循序渐进(三):让电脑掌握象棋规则相关推荐
- QT5/C++项目:基于QT的跨平台网络对战象棋(三)(推荐★★★★)
QT5/C++项目:基于QT的跨平台网络对战象棋(三)(推荐★★★★) 文章目录 QT5/C++项目:基于QT的跨平台网络对战象棋(三)(推荐★★★★) 本篇副标题: 本篇博客讲了什么or解决了什么问 ...
- 立刻、马上对你的电脑做这三件事!
前两天不小心在路边遗失了台公司笔记本,京东售价是 2 万,至于里面的工作文件价值就无法估计了.一时火烧眉毛,好在经过紧张的 60 个小时后,在派出所拿到了从广州回来的电脑. 反思之余,总结了几点可能有 ...
- 关于计算机的英语演讲稿三分钟,三分钟电脑的英文演讲稿5篇.doc
三分钟电脑的英文演讲稿5篇 三分钟电脑的英文演讲稿1 The computer is a wonderful machine. They are already widely used in indu ...
- 计算机英语第3版课后单词,PC电脑相关词汇三
PC电脑相关词汇三 name 名字 namespace 名称空间 native 本机的 nature 性质 navigate v.导航,驾驶 navigation n.导航 navigational ...
- 戏说计算机发展史,戏说IT:电脑让你三更死!那你还真死定了(第296期)
原标题:戏说IT:电脑让你三更死!那你还真死定了(第296期) [ PConline 资讯]哎~新生开学这么久了,还是没有机会回去看看我的小学妹们,好遗憾~⁄(⁄ ⁄•⁄ω⁄•⁄ ⁄)⁄,我不会放弃的 ...
- 制作适应手机网页、平板电脑(iPad)、电脑网页的三种方法
这里所说的三种方法主要指同一个网页内容同时适合手机.电脑.平板电脑浏览的三种方法. 第一种方法:电脑网页绑定手机网页 分别制作适合手机浏览和电脑浏览的网页,然后在电脑网页中绑定手机浏览的网页.比如电脑 ...
- 剑三游戏计算机配置,剑网3重制版电脑配置需求 关于选电脑二三事
关于重置版选电脑的二三事[不贴参数,通俗易懂] 这次想谈谈这个话题的原因是前几天CJ的一张推荐配置图,使得很多玩家大呼,"配置不够我要A了""哇,攒钱攒钱换电脑.&quo ...
- 电脑神器(三):三行代码实现微信多开
话不多说,我们直接上效果和演示视频: 电脑神器(三):三行代码实现微信多开 "三行代码"获取方法:微信搜索公众号"那些虚度的青春",关注后后台发送003即可立即 ...
- win8如何查看电脑配置呢?三种方法知道电脑详细配置
怎么查看电脑配置呢?很多朋友想要了解自己电脑详细的配置的时候,下面带你认识下查看电脑配置的方法. 以下方法针对win7.win8.win10系统有效果 方法一:设备管理器 我们通过鼠标右击此电脑(我的 ...
最新文章
- LIVE555中RTSP客户端接收媒体流分析及测试代码
- 从头开始搭建爬虫环境
- Codeforce-CodeCraft-20 (Div. 2)-B. String Modification (找规律+模拟)
- C++中的指针与引用(转)
- System Center 2012R2之SCVMM云部署SCOM(2-2)
- python selenium中文文档-selenium-python中文版文档
- 【报告分享】2021年人工智能安全风险及治理研究报告.pdf(附下载链接)
- 拉丁正方形 java_Leetcode 221 最大正方形 动态规划
- 搞懂:1.数据流图UML2.单代号网络图绘制3.双代号网络图绘制、工作计算法、关键路径法(含例题)
- matlab 汉字是方块,linux下Matlab 2020中文字体方框问题解决方法
- mac上更新go版本
- 群晖域名解析 DDNS ——阿里云 DNS 脚本
- 图新地球系列教程-标绘编辑:(项目实战技巧,做出好看实用的标绘)
- java的springboot项目操作阿里云OSS下载文件、查看文件内容、上传文件,自定义工具类
- 【VB-01】离线语音模块,无需语音算法开发,直接嵌入式用。
- 华为鸿蒙布局发展大会,华为开发者大会:全球瞩目的“鸿蒙”面子和里子大格局...
- 两年Java开发经验,线程面试题Java
- Mac 登录ssh服务器
- 分布式数据库id生成器的技术选型
- 速览|京东云 1-2月产品与功能更新
热门文章
- 丘仕达工作前给大家的礼物(转)
- 河南电视台:让中原文化“云”中起舞
- c语言出圈问题数学算法,出圈问题
- 谷歌分析(Google Analytics)怎么用?谷歌分析使用方法教程
- Android 判断软件app是否运行在bluestacks模拟器上(或者其他模拟器)
- 全球及中国防爆设计安全保障对讲机行业供需现状及投资盈利预测报告(2022-2027)
- 【F28335】EALLOW和EDIS指令的使用
- 微信公众号开发的测试账号配置
- 厌倦了大众字体?你可以用这个项目自创一款手写体
- 2022 Github 上传仓库