1、中国象棋游戏的设计C+论文总页数:22页1引言1.1象棋设计背景和研究意义电脑游戏行业经过二十年的发展,已经成为与影视、音乐等并驾齐驱的全球最重要的娱乐产业之一,其年销售额超过好莱坞的全年收入。游戏,作为一种娱乐活动。早期的人类社会由于生产力及科技的制约,只能进行一些户外的游戏。随着生产力的发展和科技进步,一种新的游戏方式电子游戏也随之诞生。当计算机发明以后,电子游戏又多了一个新的载体。电子游戏在整个计算机产业的带动下不断地创新、发展着。自从计算机发明,向各个领域发展,到成为我们现在每天工作和生活必不可少的一部分的这个过程中,电子游戏也逐步渗入我们每个人的娱乐活动中。而计算机已经普及的今天,对
2、于可以用计算机进行程序编辑的人来说,开发属于自己的游戏,已经不再是梦想。事实上,个人计算机软件市场的大约80%销售份额是来自游戏软件。棋牌游戏属于休闲类游戏,相对于角色扮演类游戏和即时战略类游戏等其它游戏,具有上手快、游戏时间短的特点,更利于用户进行放松休闲,为人们所喜爱,特别是棋类游戏,方便、快捷、操作简单,在休闲娱乐中占主要位置。作为中华民族悠久文化的代表之一,中国象棋不仅源远流长,而且基础广泛,作为一项智力运动,中国象棋开始走向世界。随着计算机处理速度的飞速提高,人们很早就提出了疑问:计算机是否会超越人类?世界国际象棋大师已被计算机打败,计算机已经超过了人类?而人工智能是综合性很强的一门
3、边缘学科,它的中心任务是研究如何使计算机去做那些过去只能靠人的智力才能做的工作。因此,对游戏开发过程中的人工智能技术的研究自然也就成了业界的一个热门研究方向。 1.2象棋设计研究方法对于象棋来说,核心设计主要包括人工智能算法的以及整个游戏中界面及程序辅助部分的实现,主要用 Visual C+ 进行开发,里面的MFC类库,使游戏开发更加方便,并利用人工智能相关搜索算法实现人工智能的着法生成,从而完善整个游戏的功能。本文的目标是实现一款有着一定下棋水平且交互友好的中国象棋人机对弈程序。该程序功能包括:*人机对弈;*搜索深度设定;(电脑棋力选择)*悔棋、还原;*着法名称显示;整个程序的实现可分为两大
4、部分:一、人工智能算法设计(计算机下棋引擎)该部分实现了如何让计算机下中国象棋,其中涉及人机对弈的基本理论及思想,是该程序的核心部分,同时也是本项目研究的重点所在。二、界面及程序辅助设计光有下棋引擎尚不能满足人机交互的基本要求,因此还需要一个框架(界面)来作为引擎的载体,同时提供一些诸如悔棋,还原之类的附属功能(程序辅助)。下面分别介绍各部分实现。由于界面及程序辅助部分涉及内容宽泛而又繁琐,因而本文只介绍其中重点部分。2人工智能算法设计程序的基本框架:从程序的结构上讲,大体上可以将引擎部分划分为四大块:棋局表示;着法生成;搜索算法;局面评估。程序的大概的思想是:首先使用一个数据结构来描述棋局信
5、息,对某一特定的棋局信息由着法生成器生成当前下棋方所有合法的着法并依次存入着法队列。然后通过搜索算法来逐一读取着法并调用局面评估函数对该着法所产生的后继局面进行评估打分,从中选出一个最有可能导致走棋方取胜的着法。在搜索的过程中还可以采用一些辅助手段来提高搜索的效率。其过程如下所示(图1):图 1 程序结构图下面将分别介绍程序各个部分:2.1棋局表示计算机下棋的前提是要让计算机读懂象棋。所谓读懂,即计算机应该能够清楚地了解到棋盘上的局面(棋盘上棋子的分布情况)以及下棋方所走的每一种着法。因而首先需要设计一套数据结构来表示棋盘上的局面以及着法。对于棋盘局面的表示可采用传统而简单的“棋盘数组”。即用
6、一个9*10的数组来存储棋盘上的信息,数组的每个元素存储棋盘上是否有棋子。这种表示方法简单易行(缺点是效率不是很高)。按此方法棋盘的初始情形如下所示:BYTE CChessBoard910 = R, 0, 0, P, 0, 0, p, 0, 0, r,H, 0, C, 0, 0, 0, 0, c, 0, h,E, 0, 0, P, 0, 0, p, 0, 0, e,A, 0, 0, 0, 0, 0, 0, 0, 0, a,K, 0, 0, P, 0, 0, p, 0, 0, k,A, 0, 0, 0, 0, 0, 0, 0, 0, a,E, 0, 0, P, 0, 0, p, 0, 0, e,
7、H, 0, C, 0, 0, 0, 0, c, 0, h,R, 0, 0, P, 0, 0, p, 0, 0, r;给所有棋子定义一个值:#define R_BEGIN R_KING#define R_END R_PAWN#define B_BEGIN B_KING#define B_END B_PAWN#define NOCHESS 0 /没有棋子黑方:#define B_KING 1 /黑帅#define B_CAR 2 /黑车#define B_HORSE 3 /黑马#define B_CANON 4 /黑炮#define B_BISHOP 5 /黑士#define B_ELEPHANT
8、 6 /黑象#define B_PAWN 7 /黑卒红方:#define R_KING 8 /红将#define R_CAR 9 /红车#define R_HORSE 10/红马#define R_CANON 11/红炮#define R_BISHOP 12/红士#define R_ELEPHANT 13/红相#define R_PAWN 14/红兵判断颜色:#define IsBlack(x) (x=B_BEGIN & x=R_BEGIN & x= beta) /裁剪 return beta; if (val alpha) /保留最大值 alpha = val; return alpha;2
9、.4历史启发及着法排序既然Alpha-Beta搜索算法是在“最小-最大”的基础上引入“树的裁剪”的思想以期提高效率,那么它的效率将在很大程度上取决于树的结构如果搜索了没多久就发现可以进行“裁剪”了,那么需要分析的工作量将大大减少,效率自然也就大大提高;而如果直至分析了所有的可能性之后才能做出“裁剪”操作,那此时“裁剪”也已经失去了它原有的价值(因为你已经分析了所有情况,这时的Alpha-Beta搜索已和“最小-最大”搜索别无二致了)。因而,要想保证Alpha-Beta搜索算法的效率就需要调整树的结构,即调整待搜索的结点的顺序,使得“裁剪”可以尽可能早地发生。可以根据部分已经搜索过的结果来调整将
10、要搜索的结点的顺序。因为,通常当一个局面经过搜索被认为较好时,其子结点中往往有一些与它相似的局面(如个别无关紧要的棋子位置有所不同)也是较好的。由J.Schaeffer所提出的“历史启发”(History Heuristic)就是建立在这样一种观点之上的。在搜索的过程中,每当发现一个好的走法,就给该走法累加一个增量以记录其“历史得分”,一个多次被搜索并认为是好的走法的“历史得分”就会较高。对于即将搜索的结点,按照“历史得分”的高低对它们进行排序,保证较好的走法(“历史得分”高的走法)排在前面,这样Alpha-Beta搜索就可以尽可能早地进行“裁剪”,从而保证了搜索的效率。对于着法的排序可以使用
11、各种排序算法,在程序中采用了归并排序。归并排序的空间复杂度为O(n),时间复杂度为O(nlog2n),具有较高的效率。2.5局面评估前文已经讲过了棋局表示、着法生成、搜索算法(包括搜索辅助), 在象棋程序中如果说搜索算法是心脏,那么局面评估就是大脑。搜索算法负责驱动整个程序,而局面评估则负责对搜索的内容进行判断和评价。因而搜索与局面评估是整个下棋引擎的核心。首先,先介绍一下在局面评估中需要考虑的因素。就不同的棋类可能要考虑的因素略有差异。在中国象棋中所要考虑的最基本的几个因素包括如下四点:1、子力总和子力是指某一棋子本身所具有的价值。通俗地讲就是一个棋子它值个什么价。例如,车值500的话,那可
12、能马值300,卒值80等等。所以在评估局面时,首先要考虑双方的子力总和的对比。比如红方拥有士象全加车马炮,而黑方只有残士象加双马,则红方明显占优。2、棋子位置棋子位置,或称控制区域,是指某一方的棋子在棋盘上所占据(控制)的位置。例如,沉底炮、过河卒、以及车占士角等都是较好的棋子位置状态,而窝心马、将离开底线等则属较差的棋子位置状态。3、棋子的机动性棋子的机动性指棋子的灵活度(可移动性)。例如,起始位置的车机动性较差,所以下棋讲究早出车。同样四面被憋马腿的死马机动性也较差(对于一步也不能走的棋子,可以认为其机动性为零)。4、棋子的相互关系这一点的分析较为复杂,因为一个棋子与其它子之间往往存在多重
13、关系。如:一个马可能在对方的炮的攻击之下同时它又攻击着对方的车。在程序中,估值函数最后返回的是每一方的总分的差值,而各方的总分就是上面所提到的四个因素的打分的总和。对于子力打分和控制区域打分,只要遍历棋盘,当遇到棋子时简单地去查事先定义好的“子力价值表”和“控制区域价值表”,取出相对应的值进行累加即可(这些值的具体设定参考了前人的程序并作了适当的调整,今后仍应根据电脑下棋所反映出的实际问题对这些值作适当修改)。对于机动性打分,需要求出各个子总共有多少种走法,然后根据各个子所不同的机动性价值每多一种走法就加一次相应的分数。 对棋子间相互关系的打分,要用到以下几个数据:int m_BaseValu
14、e15; /存放棋子基本价值int m_FlexValue15; /存放棋子灵活性分值short m_AttackPos109; /存放每一位置被威胁的信息BYTE m_GuardPos109; /存放每一位置被保护的信息BYTE m_FlexibilityPos109;/存放每一位置上棋子的灵活性分值int m_chessValue109; /存放每一位置上棋子的总价值其中计算机会进行所有棋子值的判断,AttackPos和GuardPos分别记录该棋子受到的威胁和被保护的值。当遍历一遍棋盘之后,子力打分、控制区域打分和机动性打分都可以完成,而关系表也可以填完。之后,再根据关系表来具体考察棋子
15、的相互关系,进行关系打分。分析关系时,首先,对王的攻击保护应分离出来单独考虑,因为对王的保护没有任何意义,一旦王被吃掉整个游戏就结束了。其次,对一个普通子,当它既受到攻击又受到保护的时候要注意如下几个问题:1、攻击者子力小于被攻击者子力,攻击方将愿意换子。比如,一个车正遭受一个炮的攻击,那么任何对车的保护都将失去意义对方肯定乐意用一个炮来换一个车。2、多攻击单保护的情况,并且攻击者最小子力小于被攻击者子力与保护者子力之和,则攻击方可能以一子换两子。3、三攻击两保护的情况,并且攻击者子力较小的二者之和小于被攻击者子力与保护者子力之和,则攻击方可能以两子换三子。4、攻击方与保护方数量相同,并且攻击
16、者子力小于被攻击者子力与保护者子力之和再减去保护者中最大子力,则攻击方可能以n子换n子。当然,上述四条只是覆盖了最常见的几种情况,覆盖并不全面。而且,在程序中并没有直接地重新考虑双方兑子之后的控制区域及机动性变化情况(之所以说没有“直接地重新考虑”,是因为搜索继续展开结点后仍会考虑这些因素,只是目前不知这样效果是否受影响考察这两种方法在效果上的差异需要一定数量的试验数据的支持)。所以,如果今后要对引擎进行改进,提高程序的下棋水平的话,还应当在此进行研究。2.6程序组装至此,已具备了实现一款中国象棋对弈程序引擎部分的所有要素,将上述模块分别写作.h头文件。如下:Define.h象棋相关定义。包括
17、棋盘局面和着法的表示。CMoveGenerator.h着法生成器。就当前局面生成某一方所有合法着法。CSearchEngine.h搜索部分。使用搜索求出最佳着法。HistoryHeuristic.h历史启发。Alpha-Beta搜索之补充,以提高搜索效率。着法排序。对着法按其历史得分进行降序排序,以提高搜索效率。CEveluate.h局面评估。为某一特定局面进行评分。当实现了引擎部分的各要素时,可先建了一个Win32控制台项目,之后只要再添加一个.cpp文件负责接受用户的输入、调用搜索函数、显示搜索结果,便可简单的测试引擎了(采用输入着法的起点坐标和终点坐标的方式来传送用户走棋的信息。同样,程序显示计算机走棋的起点坐标和终点坐标来做出回应)。此后,等到界面部分初步完成,引擎的上述各模块无需作任何改动,仍以.h头文件的形式加入界面工程,只要由界面中的某个.cpp文件调用搜索函数即可。这种连接
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1