完整版中国象棋游戏设计与实现毕业设计毕业论文设计.docx

上传人:b****1 文档编号:15180004 上传时间:2023-07-02 格式:DOCX 页数:17 大小:44.26KB
下载 相关 举报
完整版中国象棋游戏设计与实现毕业设计毕业论文设计.docx_第1页
第1页 / 共17页
完整版中国象棋游戏设计与实现毕业设计毕业论文设计.docx_第2页
第2页 / 共17页
完整版中国象棋游戏设计与实现毕业设计毕业论文设计.docx_第3页
第3页 / 共17页
完整版中国象棋游戏设计与实现毕业设计毕业论文设计.docx_第4页
第4页 / 共17页
完整版中国象棋游戏设计与实现毕业设计毕业论文设计.docx_第5页
第5页 / 共17页
完整版中国象棋游戏设计与实现毕业设计毕业论文设计.docx_第6页
第6页 / 共17页
完整版中国象棋游戏设计与实现毕业设计毕业论文设计.docx_第7页
第7页 / 共17页
完整版中国象棋游戏设计与实现毕业设计毕业论文设计.docx_第8页
第8页 / 共17页
完整版中国象棋游戏设计与实现毕业设计毕业论文设计.docx_第9页
第9页 / 共17页
完整版中国象棋游戏设计与实现毕业设计毕业论文设计.docx_第10页
第10页 / 共17页
完整版中国象棋游戏设计与实现毕业设计毕业论文设计.docx_第11页
第11页 / 共17页
完整版中国象棋游戏设计与实现毕业设计毕业论文设计.docx_第12页
第12页 / 共17页
完整版中国象棋游戏设计与实现毕业设计毕业论文设计.docx_第13页
第13页 / 共17页
完整版中国象棋游戏设计与实现毕业设计毕业论文设计.docx_第14页
第14页 / 共17页
完整版中国象棋游戏设计与实现毕业设计毕业论文设计.docx_第15页
第15页 / 共17页
完整版中国象棋游戏设计与实现毕业设计毕业论文设计.docx_第16页
第16页 / 共17页
完整版中国象棋游戏设计与实现毕业设计毕业论文设计.docx_第17页
第17页 / 共17页
亲,该文档总共17页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

完整版中国象棋游戏设计与实现毕业设计毕业论文设计.docx

《完整版中国象棋游戏设计与实现毕业设计毕业论文设计.docx》由会员分享,可在线阅读,更多相关《完整版中国象棋游戏设计与实现毕业设计毕业论文设计.docx(17页珍藏版)》请在冰点文库上搜索。

完整版中国象棋游戏设计与实现毕业设计毕业论文设计.docx

完整版中国象棋游戏设计与实现毕业设计毕业论文设计

优秀论文审核通过

未经允许切勿外传

中国象棋游戏的设计与实现

摘要

象棋程序的实现可以被分为人工智能和界面程序辅助两大部分。

人工智能部分主要体现计算机的下棋思路,既计算机如何进行思考并以最佳走法完成下一步,先由相应的搜索算法进行搜索,并对各种可能的走法进行估值,从中选择胜利面最大的一步;而界面及程序辅助部分主要便于用户通过以前的下棋步骤,更好地调整下棋思路,着法显示使用户能够清楚地知道下棋过程,更准确地把握整个局面。

本文首先研究了中国象棋在计算机中的表示问题,接着讨论如何产生着法一系列相关内容。

其次研究了博弈树的极小极大搜索技术及在此基础上发展起来的Alpha-Beta剪枝算法,使用MFC文档视图体系结构和VisualC++开发工具,实现了一个具有一定棋力的中国象棋人机对弈程序。

关键词:

中国象棋;人工智能;博弈树;Alpha-Beta搜索

TheDesignandImplementationofChineseChess

Abstract

Theimplementationofachessprogramcanbedecomposedintotwomajorparts:

theartificialintelligenceandtheuserinterfaceandprogramassist.Thepartofartificialintelligenceshowsthewayofcomputerthinking,andwhichstepisthebeststepwouldbedecidedbyit.Firstly,thecomputerusessearchalgorithmstosearch,andthenevaluateseveryimpossiblestep,finallychosesthebestone,theotherpartisusedfortheplayertoadjustcomputer,thendiscussestheintegratedcomputerMFCSDIdocumentviewarchitecturebyusingVisualC++.

Keywords:

Chinesechess;ArtificialIntelligence;Gametree;Alpha-Betasearching

目录

论文总页数:

22页

1引言1

1.1象棋设计背景和研究意义1

1.2象棋设计研究方法1

2人工智能算法设计2

2.1棋局表示3

2.2着法生成4

2.3搜索算法5

2.4历史启发及着法排序9

2.5局面评估9

2.6程序组装11

3界面及程序辅助设计12

3.1界面基本框架12

3.2多线程13

3.3着法名称显示14

3.4悔棋和还原15

4系统实现16

结论19

参考文献20

致谢21

声明22

 

1引言

1.1象棋设计背景和研究意义

电脑游戏行业经过二十年的发展,已经成为与影视、音乐等并驾齐驱的全球最重要的娱乐产业之一,其年销售额超过好莱坞的全年收入。

游戏,作为一种娱乐活动。

早期的人类社会由于生产力及科技的制约,只能进行一些户外的游戏。

随着生产力的发展和科技进步,一种新的游戏方式——电子游戏也随之诞生。

当计算机发明以后,电子游戏又多了一个新的载体。

电子游戏在整个计算机产业的带动下不断地创新、发展着。

自从计算机发明,向各个领域发展,到成为我们现在每天工作和生活必不可少的一部分的这个过程中,电子游戏也逐步渗入我们每个人的娱乐活动中。

而计算机已经普及的今天,对于可以用计算机进行程序编辑的人来说,开发属于自己的游戏,已经不再是梦想。

事实上,个人计算机软件市场的大约80%销售份额是来自游戏软件。

棋牌游戏属于休闲类游戏,相对于角色扮演类游戏和即时战略类游戏等其它游戏,具有上手快、游戏时间短的特点,更利于用户进行放松休闲,为人们所喜爱,特别是棋类游戏,方便、快捷、操作简单,在休闲娱乐中占主要位置。

作为中华民族悠久文化的代表之一,中国象棋不仅源远流长,而且基础广泛,作为一项智力运动,中国象棋开始走向世界。

随着计算机处理速度的飞速提高,人们很早就提出了疑问:

计算机是否会超越人类?

世界国际象棋大师已被计算机打败,计算机已经超过了人类?

而人工智能是综合性很强的一门边缘学科,它的中心任务是研究如何使计算机去做那些过去只能靠人的智力才能做的工作。

因此,对游戏开发过程中的人工智能技术的研究自然也就成了业界的一个热门研究方向。

1.2象棋设计研究方法

对于象棋来说,核心设计主要包括人工智能算法的以及整个游戏中界面及程序辅助部分的实现,主要用VisualC++进行开发,里面的MFC类库,使游戏开发更加方便,并利用人工智能相关搜索算法实现人工智能的着法生成,从而完善整个游戏的功能。

本文的目标是实现一款有着一定下棋水平且交互友好的中国象棋人机对弈程序。

该程序功能包括:

*人机对弈;

*搜索深度设定;

(电脑棋力选择)

*悔棋、还原;

*着法名称显示;

整个程序的实现可分为两大部分:

一、人工智能算法设计(计算机下棋引擎)

该部分实现了如何让计算机下中国象棋,其中涉及人机对弈的基本理论及思想,是该程序的核心部分,同时也是本项目研究的重点所在。

二、界面及程序辅助设计

光有下棋引擎尚不能满足人机交互的基本要求,因此还需要一个框架(界面)来作为引擎的载体,同时提供一些诸如悔棋,还原之类的附属功能(程序辅助)。

下面分别介绍各部分实现。

由于界面及程序辅助部分涉及内容宽泛而又繁琐,因而本文只介绍其中重点部分。

2人工智能算法设计

程序的基本框架:

从程序的结构上讲,大体上可以将引擎部分划分为四大块:

棋局表示;

着法生成;

搜索算法;

局面评估。

程序的大概的思想是:

首先使用一个数据结构来描述棋局信息,对某一特定的棋局信息由着法生成器生成当前下棋方所有合法的着法并依次存入着法队列。

然后通过搜索算法来逐一读取着法并调用局面评估函数对该着法所产生的后继局面进行评估打分,从中选出一个最有可能导致走棋方取胜的着法。

在搜索的过程中还可以采用一些辅助手段来提高搜索的效率。

其过程如下所示(图1):

图1程序结构图

下面将分别介绍程序各个部分:

2.1棋局表示

计算机下棋的前提是要让计算机读懂象棋。

所谓读懂,即计算机应该能够清楚地了解到棋盘上的局面(棋盘上棋子的分布情况)以及下棋方所走的每一种着法。

因而首先需要设计一套数据结构来表示棋盘上的局面以及着法。

对于棋盘局面的表示可采用传统而简单的“棋盘数组”。

即用一个9*10的数组来存储棋盘上的信息,数组的每个元素存储棋盘上是否有棋子。

这种表示方法简单易行(缺点是效率不是很高)。

按此方法棋盘的初始情形如下所示:

BYTECChessBoard[9][10]={

R,0,0,P,0,0,p,0,0,r,

H,0,C,0,0,0,0,c,0,)。

其中b是分枝因子,即针对各种局面的合法着法的数目的平均值,n是搜索的深度。

对于中国象棋而言,在中盘时平均着法数目大约是40种左右,那么搜索4层需要检查250万条路线,搜索5层需要检查1亿条路线,搜索6层需要检查40亿条路线!

Alpha-Beta搜索能在不影响搜索精度的前提下大幅减少工作量。

因为,如果考虑到下棋是一个你来我往的交替进行并且相互“较劲”的过程。

由于每一方都会尽可能将局面导向对自己有利而对对方不利的方向(假定下棋双方对棋局有着同样的认知,即你认为对你很糟糕的局面,在你的对手看来则是对他很有利的局面),那么某些局面由于能够产生出很糟糕的局面因而根本没有再继续考虑的价值。

所以当你看到某个局面有可能产生很糟糕的局面时(确切地说这里的“很糟糕”是与之前分析的情况相比较而言的),你应当立刻停止对其剩余子结点的分析——不要对它再抱任何幻想了,如果你选择了它,那么你必将得到那个很糟糕的局面,甚至可能更糟……这样一来便可以在很大程度上减少搜索的工作量,提高搜索效率,这称为“树的裁剪”。

下面用图来进一步说明“树的裁剪”。

为了简便起见,将博弈树进行了简化——每个结点只有三个分支,实际情况中,刚才讲过在盘中应有大约40个分支。

假定棋盘上的局面发展到了结点A(图3),现在轮到你走棋了,你是“最大的一方”——即你希望棋局的分值尽可能的高。

用搜索两层来看一看“树的裁剪”对提高搜索效率的帮助。

图中表示该结点要取子结点中的最大值;表示该结点要取子结点中的最小值。

图3树的裁剪

首先,考察结点A的子结点B。

结点B所属的这一层是轮到你的对手——“最小者”来走棋了,目的是使得棋局的分值尽可能的小。

依次考察结点B的各个子结点,查看它们的分值(因为事先约定好了搜索两层,现在已达到搜索深度的要求了,所以就停下来调用局面评估函数来给它打分)。

结点B的第一个子结点(从左到右算起)返回10,第二个子结点返回了-5,第三个子结点返回了2。

由于结点B这层是你的对手来做选择,假设他一定会做出明智的选择(你不能寄希望于你的对手会走出一步“昏招”),那么他会选择返回值为-5的那个结点。

-5最终也就成了从结点B传递回的值,即倘若你(现在位于结点A)选择了产生结点B的走法,使得局面发展到了结点B。

那么下一步,你的对手的选择就会使得棋局发展成为分值为-5的那个结点所表示的局面。

再来分析结点A的第二个子结点C,结点C与结点B同属一层,它依然是轮到你的对手作选择。

依次查看结点C的各个子结点的分值,其第一个子结点返回了-8……

采用“裁剪”方法。

不必再继续考察结点C的剩余子结点了,因为结点C已经够糟糕的了,不管结点C的剩余子结点有怎样的分值,它最多只能传回-8(有可能其剩余子结点中还有分值更小的结点,因而结点C还有可能传回更小的值)。

而与前面已经分析过的结点B所传回-5相比较,作为“最大一方”的你显然更不愿意看到-8的局面。

所以,你当然不会选择相应的着法使得局面发展成为结点C。

因为那样的话,下一步你的对手就会带给你一个分值不高于-8的局面。

由此,在不影响搜索质量的前提下避免了搜索“无价值的”结点C的剩余子结点的大量工作,从而节省了宝贵时间,为在同样机器配置下搜索更多的层数提供了可能。

“最小-最大”的思想再加上“对树的裁剪”,这就是Alpha-Beta搜索算法的核心。

最基本的Alpha-Beta算法的代码如下:

intAlphaBeta(intdepth,intalpha,intbeta)

{

if(depth==0)如果是叶子节点(到达搜索深度要求)

returnEvaluate();则由局面评估函数返回估值

GenerateLegalMoves();产生所有合法着法

while(MovesLeft())遍历所有着法

{

MakeNextMove();执行着法

intval=-AlphaBeta(depth-1,-beta,-alpha);递归调用UnmakeMove();撤销着法

if(val>=beta)裁剪

returnbeta;

if(val>alpha)保留最大值

alpha=val;

}

returnalpha;

}

2.2历史启发及着法排序

既然Alpha-Beta搜索算法是在“最小-最大”的基础上引入“树的裁剪”的思想以期提高效率,那么它的效率将在很大程度上取决于树的结构——如果搜索了没多久就发现可以进行“裁剪”了,那么需要分析的工作量将大大减少,效率自然也就大大提高;而如果直至分析了所有的可能性之后才能做出“裁剪”操作,那此时“裁剪”也已经失去了它原有的价值(因为你已经分析了所有情况,这时的Alpha-Beta搜索已和“最小-最大”搜索别无二致了)。

因而,要想保证Alpha-Beta搜索算法的效率就需要调整树的结构,即调整待搜索的结点的顺序,使得“裁剪”可以尽可能早地发生。

可以根据部分已经搜索过的结果来调整将要搜索的结点的顺序。

因为,通常当一个局面经过搜索被认为较好时,其子结点中往往有一些与它相似的局面(如个别无关紧要的棋子位置有所不同)也是较好的。

由J.Schaeffer所提出的“历史启发”(HistoryHeuristic)就是建立在这样一种观点之上的。

在搜索的过程中,每当发现一个好的走法,就给该走法累加一个增量以记录其“历史得分”,一个多次被搜索并认为是好的走法的“历史得分”就会较高。

对于即将搜索的结点,按照“历史得分”的高低对它们进行排序,保证较好的走法(“历史得分”高的走法)排在前面,这样Alpha-Beta搜索就可以尽可能早地进行“裁剪”,从而保证了搜索的效率。

对于着法的排序可以使用各种排序算法,在程序中采用了归并排序。

归并排序的空间复杂度为O(n),时间复杂度为O(nlog2n),具有较高的效率。

2.3局面评估

前文已经讲过了棋局表示、着法生成、搜索算法(包括搜索辅助),在象棋程序中如果说搜索算法是心脏,那么局面评估就是大脑。

搜索算法负责驱动整个程序,而局面评估则负责对搜索的内容进行判断和评价。

因而搜索与局面评估是整个下棋引擎的核心。

首先,先介绍一下在局面评估中需要考虑的因素。

就不同的棋类可能要考虑的因素略有差异。

在中国象棋中所要考虑的最基本的几个因素包括如下四点:

1、子力总和

子力是指某一棋子本身所具有的价值。

通俗地讲就是一个棋子它值个什么价。

例如,车值500的话,那可能马值300,卒值80等等。

所以在评估局面时,首先要考虑双方的子力总和的对比。

比如红方拥有士象全加车马炮,而黑方只有残士象加双马,则红方明显占优。

2、棋子位置

棋子位置,或称控制区域,是指某一方的棋子在棋盘上所占据(控制)的位置。

例如,沉底炮、过河卒、以及车占士角等都是较好的棋子位置状态,而窝心马、将离开底线等则属较差的棋子位置状态。

3、棋子的机动性

棋子的机动性指棋子的灵活度(可移动性)。

例如,起始位置的车机动性较差,所以下棋讲究早出车。

同样四面被憋马腿的死马机动性也较差(对于一步也不能走的棋子,可以认为其机动性为零)。

4、棋子的相互关系

这一点的分析较为复杂,因为一个棋子与其它子之间往往存在多重关系。

如:

一个马可能在对方的炮的攻击之下同时它又攻击着对方的车。

在程序中,估值函数最后返回的是每一方的总分的差值,而各方的总分就是上面所提到的四个因素的打分的总和。

对于子力打分和控制区域打分,只要遍历棋盘,当遇到棋子时简单地去查事先定义好的“子力价值表”和“控制区域价值表”,取出相对应的值进行累加即可(这些值的具体设定参考了前人的程序并作了适当的调整,今后仍应根据电脑下棋所反映出的实际问题对这些值作适当修改)。

对于机动性打分,需要求出各个子总共有多少种走法,然后根据各个子所不同的机动性价值每多一种走法就加一次相应的分数。

对棋子间相互关系的打分,要用到以下几个数据:

intm_BaseValue[15];存放棋子基本价值

intm_FlexValue[15];存放棋子灵活性分值

shortm_AttackPos[10][9];存放每一位置被威胁的信息

BYTEm_GuardPos[10][9];存放每一位置被保护的信息

BYTEm_FlexibilityPos[10][9];存放每一位置上棋子的灵活性分值

intm_chessValue[10][9];存放每一位置上棋子的总价值

其中计算机会进行所有棋子值的判断,AttackPos和GuardPos分别记录该棋子受到的威胁和被保护的值。

当遍历一遍棋盘之后,子力打分、控制区域打分和机动性打分都可以完成,而关系表也可以填完。

之后,再根据关系表来具体考察棋子的相互关系,进行关系打分。

分析关系时,首先,对王的攻击保护应分离出来单独考虑,因为对王的保护没有任何意义,一旦王被吃掉整个游戏就结束了。

其次,对一个普通子,当它既受到攻击又受到保护的时候要注意如下几个问题:

1、攻击者子力小于被攻击者子力,攻击方将愿意换子。

比如,一个车正遭受一个炮的攻击,那么任何对车的保护都将失去意义——对方肯定乐意用一个炮来换一个车。

2、多攻击\单保护的情况,并且攻击者最小子力小于被攻击者子力与保护者子力之和,则攻击方可能以一子换两子。

3、三攻击\两保护的情况,并且攻击者子力较小的二者之和小于被攻击者子力与保护者子力之和,则攻击方可能以两子换三子。

4、攻击方与保护方数量相同,并且攻击者子力小于被攻击者子力与保护者子力之和再减去保护者中最大子力,则攻击方可能以n子换n子。

当然,上述四条只是覆盖了最常见的几种情况,覆盖并不全面。

而且,在程序中并没有直接地重新考虑双方兑子之后的控制区域及机动性变化情况(之所以说没有“直接地重新考虑”,是因为搜索继续展开结点后仍会考虑这些因素,只是目前不知这样效果是否受影响——考察这两种方法在效果上的差异需要一定数量的试验数据的支持)。

所以,如果今后要对引擎进行改进,提高程序的下棋水平的话,还应当在此进行研究。

2.4程序组装

至此,已具备了实现一款中国象棋对弈程序引擎部分的所有要素,将上述模块分别写作.(UINTnFlags,CPointpoint)

{

……

}

当用户在窗口客户区按下鼠标左键时,程序就会调用OnLButtonDown(UINTnFlags,CPointpoint)函数来进行响应。

其中第二个参数CPointpoint是在本程序中所要用到的,它给出了当鼠标左键被按下时,鼠标指针的位置坐标。

可以通过这一信息来得知用户的走法。

在OnLButtonDown函数里处理如下两种操作:

1、如果用户点击鼠标的位置落在己方的棋子上,表示用户选中了该棋子,下一步将移动该子进行走棋(也可能用户下一步将会选择己方另外的棋子,总之这一操作会记录下用户所选的将要走的棋子)。

2、如果之前用户已经选过了棋子,那么这一次的点击(如果不是另选本方的其它棋子的话)表达了用户的一次走棋过程。

在收到用户传达的走棋信息后,可先判断该着法是否合法(是否符合中国象棋的游戏规则),如果合法,则执行之。

紧接着调用引擎的搜索函数计算出计算机对用户着法的应着,然后执行该应着。

如此,在OnLButtonDown函数里,实现了人与机器的对弈(当然每走一步棋,也还需要绘图函数来显示棋盘局面的更新)。

以上三部分并非界面程序的全部,而仅仅是与程序密切相关的部分。

此外还有其它部分对程序同样必不可少,但这些部分主要由MFC自动生成,无需人为改动,故在此不多做介绍。

2.5多线程

如采用单线程方式,按照如下顺序编写代码:

用户走棋 —〉计算机思考并走棋

按这种方式编写的程序似乎毫无问题,程序运行一切正常。

然而,在给程序加入这些功能(后面将会在讲到其实现)后,程序出现了异常:

有时对用户方的功能完全正确,而对电脑方的有些功能却不起作用!

是由于程序在进行搜索时会占用大量的CPU时间,因而阻塞了位于同一线程内的其他指令,使之无法正常工作。

解决方案就是另外开一个线程,让各程序分开于多个线程。

启动一个新的线程的方法非常简单,只需调用函数AfxBeginThread即可,函数原型:

CWinThread*AfxBeginThread(

AFX_THREADPROCThinkProc,

LPVOIDpParam,

intnPriority=THREAD_PRIORITY_NORMAL,

UINTnStackSize=0,

DWORDdwCreateFlags=0,

LPSECURITY_ATTRIBUTESlpSecurityAttrs=NULL

);

该函数启动一个新的线程并返回一个指向该新线程对象的指针,然后新的线程与启动该新线程的线程同时运行。

该函数的第一个参数AFX_THREADPROCThinkProc指定了线程函数。

线程函数的内容即为新线程所要执行的内容,线程函数执行完毕,新线程结束(自动销毁)。

线程函数必须被定义为全局函数,其返回值类型必须是UINT,必须有一个LPVOID类型的参数。

可以把调用引擎部分的搜索函数的代码以及完成走棋动作的代码放入所定义的思考线程内,如下:

DWORDWINAPIThinkProc(LPVOIDpParam)

{

CChessDlg*pDlg=(CChessDlg*)pParam;

pDlg->Think();计算机思考并走棋

return0;

}

然后,只要将原先调搜索函数并完成走棋的代码代之以调用AfxBeginThread来启动新线程即可,实现了程序的多线程,不能正常工作的问题也就随之解决了。

2.6着法名称显示

每当下棋方(用户或是计算机)走一步棋,在棋盘旁边的一个列表框控件(ListBox)中按照中国象棋关于着法描述的规范要求显示出该着法的名称。

如:

红炮二平五、黑马8进7此类。

为了获得该着法名称,写了一个六百余行的函数。

其功能就是将被移动的棋子类型以及走法的起点坐标、终点坐标这些信息转换成中国象棋所规范的着法名称。

由于该函数主要涉及的是中国象棋关于着法表示的规范要求,故在此不对其具体实现做额外的解释。

主要讨论的是如何对列表框控件(ListBox)进行操作,以显示或删除着法名称。

首先,在ChessDlg下定义以下函数:

this->GetMoveStr(nFromX,nFromY,nToX,nToY,nSourceID);

用来获得刚下的一步棋的走法;

voidCChessDlg:

:

AddChessRecord(intnFromX,intnFromY,intnToX,intnToY,intnUserChessColor,intnSourceID)

将走法添加进下棋记录;

然后,显示在Listbox中。

当列表框中的项的数目超过列表框的显示范围时,列表框会自动添加垂直滚动条(前提是其VerticalScrollbar属性要为True——该属性默认即为True)。

但是显示的内容依然是最早加进来的项。

在控件属性里选择VerticalScroll,使得列表框可垂直滚动以显示最新的着法名称。

想要从列表框中删除项时,可以使用

m_lstChessRecord.DeleteString(m_lstChessRecord.GetCount()-1);减一之后正好是最后一项的行号。

2.7悔棋和还原

悔棋和还原是棋类软件中较为基本的功能。

要实现悔棋和还原功能,首先要明确哪些信息应当被保存以供悔棋和还原所使用。

在程序中保存了如下信息:

棋局表示中所定义的棋盘数组;

各棋子的贴图位置。

这里需要特别说明的是通常象棋程序处于程序效率的考虑并不保存所有棋子的信息,而只是保存之前一步的走棋信息。

此后当悔棋的时候,需要撤销着法;还原的时候,需要执行着法。

然而,在编写自己的程序时一来考虑到程序的可读性和不易出错性,二来考虑到对当今的计算机的配置来说这点开销基本上不会对程序的效率产生什么影响。

因此保存了全部棋子的信息。

根据所要保存的数据定义了如下基本结构类型:

typedefstruct

{

CHESSMOVEcmC

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 医药卫生 > 基础医学

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2