ImageVerifierCode 换一换
格式:DOCX , 页数:24 ,大小:490.22KB ,
资源ID:26638434      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/26638434.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(中国象棋游戏开发设计报告.docx)为本站会员(b****3)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

中国象棋游戏开发设计报告.docx

1、中国象棋游戏开发设计报告 中国象棋游戏开发设计报告班级: 小组编号: 小组成员: 指导老师: 一、开发的目的和意义面向对象程序设计作为一门软件设计的课程,具有极强的实践性,要求学生具备灵活应用理论知识的能力及面向对象程序设计技能的基础。通过游戏开发,学生能了解C+面向对象的设计方法与技巧,有效地、深刻地理解课程内容,体会理论、方法和设计原则,培养分析实际问题和解决问题的能力,具备使用面向对象程序设计开发工具设计实际系统的能力。还能够了解并通过使用MFC,掌握一种可视化编程的方法,并通过游戏的开发加深对可视化编程的理解。同时,可以提高运用C+编程语言解决实际问题的能力。棋牌游戏属于休闲类游戏,具

2、有上手快、游戏时间短的特点,更利于用户进行放松休闲,为人们所喜爱,特别是棋类游戏,方便、快捷、操作简单,在休闲娱乐中占主要位置。中国象棋作为中国自古以来的经典棋牌游戏之一,一直都是人之间的较量,将中国象棋制作成游戏,可以实现人与计算机之间的对弈。而且人工智能是综合性很强的一门边缘学科,它的中心任务是研究如何使计算机去做那些过去只能靠人的智力才能做的工作。开发出了计算机象棋游戏,以后不仅仅可以进行休闲游戏,还能锻炼自己的智力和象棋技术,更加方便了人们的日常生活。二、功能描述和分析(用户需求分析)2.1开发背景 我们周围有许多同学喜欢下象棋,尤其是男同学,希望能有人可以和自己下象棋,但这种意愿常因

3、为受到条件的限制而难以如愿,比如说需要身边刚好有现成的棋盘棋子,比如说需要是同样懂得中国象棋的对手,但是大家都知道我们这所大学男性同学占少数,即便是条件都满足了,还要考虑这位对手是否有何自己下棋的心情。 这时,如果有一台计算机,一个能够支持人机对弈的程序,上面的问题迎刃而解。而我们小组的这个想起游戏设计,正是希望能够做出一款拥有良好性能,良好的智能,能够满足大多数爱好象棋的同学的需求中国象棋人机对弈程序。2.2用户需求分析 一款能够与用户对弈,满足用户需求的中国象棋程序,需要有棋盘棋子的局面、鼠标响应控制棋子移动、棋子的走法规则、人机对弈的搜索算法、避免异常引入的多线程、胜负判断,具体分析如下

4、:2.2.1棋盘棋子的局面 作为中国象棋的这项游戏,其必不可少的是就是棋子和棋盘,没有这两个部分,想起功能无法实现,不仅仅如此,如果,仅仅有棋子和棋盘,而没有将两者结合起来,那么,也将无法实现中国象棋的游戏功能,所以,棋子和棋盘的设计在这个游戏设计中至关重要。2.2.2鼠标响应在对弈中,棋子是必须可以移动的,不然游戏无法进行。因此,鼠标左键点击是必不可少的一部分。2.2.3棋子的功能分析:中国象棋中各色的象棋棋子的功能使象棋具有了真正的趣味性,中国象棋的棋子的类型大致分为:帅(将)、士、象、马、车、炮、兵(卒)等几个类型。帅(将):红方中的帅和黑方中的将的功能相同,都是只能在九宫格中进行横向和

5、竖向的移动,每次移动一格,并且不能移动超出九宫格,帅和将不能见面。士:士在整片棋盘中,和帅的移动范围类似,也是只能在九宫格中移动,不过士的移动方向是对角线,并且每次只能在一个格子中移动。象:象的走法遵循“象走田”的原则,不能绊象腿。马:马的走法遵循“马走日”的原则,不能绊马腿。车:在整块棋盘中,车可以横向或纵向3移动任意格。炮:每次移动和车的类似,但是在吃对方棋子的时候必须中间有且只能有一个棋子的间隔。兵(卒):红方的兵和黑方的卒的功能相同,特点是只能向对方前进,而不能后退,过河之前不能横向移动,过河之后可以横向移动,不管是前进还是横向移动,每次都只能移动一格。2.2.4良好的人机对弈要实现人

6、机的对弈,搜索算法是很重要的一部分。关于棋类对弈程序中的搜索算法,已有成熟的Alpha-Beta搜索算法。我们在程序中直接借鉴了Alpha-Beta搜索算法并辅以历史启发。Alpha-Beta搜索算法:在中国象棋里,双方棋手获得相同的棋盘信息。他们轮流走棋,目的就是吃掉对方的将或帅,或者避免自己的将或帅被吃。搜索算法的搜索过程很漫长,因此对搜索算法进行简化是有必要的。2.2.5多线程的必要性由于程序在进行搜索时会占用大量的CPU时间,因而阻塞了位于同一线程内的其他指令,使之无法正常工作,因而引入了多线程的思想另外开一个线程,让各程序分开于多个线程。就可以解决程序异常的问题了,因此,多线程思想的

7、引入是有必要的。2.2.6判断胜负游戏需要判断最后由谁胜出三、采用的开发工具和技术,开发环境,适用环境开发工具:Visual C+ MFC工程;开发环境:win7;适用环境:windows系统;四、小组成员分工初始化、局面设计部分(贺景);判断胜负、棋子走法部分(邹京甫);鼠标响应、绘图部分(吴鑫);搜索引擎部分等由组员共同完成。五、具体开发方法和过程5.1初始化部分OnInitDialog()负责的是对话框的初始化。可以把有关中国象棋的棋局初始化情况也放在了这里面。初始化的内容包括:对引擎部分所用到的变量的初始化。包括对棋盘上的棋子位置进行初始化(棋盘数组的初始化),对搜索深度、当前走棋方标

8、志、棋局是否结束标志等的初始化;对棋盘、棋子的贴图位置(即棋盘、棋子在程序中实际显示位置)的初始化;对程序辅助部分所用到的一些变量的初始化。棋盘、棋子样式的默认形式,以及着法名称列表的初始化等。1.对棋盘的初始化memcpy(m_byChessBoard,InitChessBoard,90);2.对棋盘、棋子的贴图位置(即棋盘、棋子在程序中实际显示位置)的初始化;MemDC.SelectObject(&pOldBmp);/恢复内存Dc的原位图3.对程序辅助部分所用到的一些变量的初始化棋盘、棋子样式的默认形式,下棋模式的默认选择,以及着法名称列表的初始化等。初始化部分的代码如下:BOOL CCh

9、essDlg:OnInitDialog() CDialog:OnInitDialog(); / Add About. menu item to system menu. / IDM_ABOUTBOX must be in the system command range. ASSERT(IDM_ABOUTBOX & 0xFFF0) = IDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX AppendMenu(MF_SEPARATOR); pSysMenu-AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); SetIcon(m_

10、hIcon, TRUE); / Set big icon SetIcon(m_hIcon, FALSE); / Set small icon /彩色进度条设置 m_progressThink.SetStartColor(RGB(0xFF,0xFF,0x00);/黄色 m_progressThink.SetEndColor(RGB(0x00,0x93,0x00); /绿色 m_progressThink.SetBkColor(RGB(0xE6,0xE6,0xFA); /淡紫色 m_progressThink.SetTextColor(RGB(0,0,255); m_progressThink.S

11、howPercent(1); m_tooltip.Create(this); m_tooltip.Activate(1); m_Chessman.Create(IDB_CHESSMAN,36,14,RGB(0,255,0);/创建含有棋子图形的ImgList,用于绘制棋子 /下面这段代码取棋盘图形的宽,高 BITMAP BitMap; m_BoardBmp.LoadBitmap(IDB_CHESSBOARD); m_BoardBmp.GetBitmap(&BitMap); /取BitMap 对象 m_nBoardWidth=BitMap.bmWidth; /棋盘宽度 m_nBoardHeigh

12、t=BitMap.bmHeight;/棋盘高度 m_BoardBmp.DeleteObject(); memcpy(m_byChessBoard,InitChessBoard,90);/初始化棋盘 memcpy(m_byShowChessBoard,InitChessBoard,90); memcpy(m_byBackupChessBoard,InitChessBoard,90); m_pSE-SetSearchDepth(3); /设定搜索层数为3 m_pSE-SetMoveGenerator(m_pMG);/给搜索引擎设定走法产生器 m_pSE-SetEveluator(m_pEvel);

13、 /给搜索引擎设定估值核心 m_pSE-SetUserChessColor(m_nUserChessColor); /设定用户为黑方或红方 m_pSE-SetThinkProgress(&m_progressThink); /设定进度条 m_MoveChess.nChessID=NOCHESS;/将移动的棋子清空 return TRUE; / return TRUE unless you set the focus to a control5.2局面设计游戏设计中,我们的象棋棋盘采用的是直接加载位图生成棋盘,图片的大小是宽度377*高度417,棋盘上每个格子的大小:39*39,图片格式为:BM

14、P。棋子部分是通过加载位图实现的,图片的大小是:宽度32*高度32,图片的格式也是BMP。我们用一个10*9的数组来存储棋盘上的信息,数组的每个元素存储棋盘上是否有棋子。棋盘的初始情形如下所示(图1是整个棋盘与棋子的局面图):const BYTE InitChessBoard109=B_CAR,B_HORSE,B_ELEPHANT,B_BISHOP,B_KING,B_BISHOP,B_ELEPHANT,B_HORSE,B_CAR,NOCHESS,NOCHESS,NOCHESS,NOCHESS,NOCHESS,NOCHESS,NOCHESS,NOCHESS,NOCHESS,NOCHESS,B_C

15、ANON,NOCHESS,NOCHESS,NOCHESS,NOCHESS,NOCHESS,B_CANON,NOCHESS,B_PAWN,NOCHESS,B_PAWN,NOCHESS,B_PAWN,NOCHESS,B_PAWN,NOCHESS,B_PAWN,NOCHESS,NOCHESS,NOCHESS,NOCHESS,NOCHESS,NOCHESS,NOCHESS,NOCHESS,NOCHESS,/楚河 /汉界NOCHESS,NOCHESS,NOCHESS,NOCHESS,NOCHESS,NOCHESS,NOCHESS,NOCHESS,NOCHESS,R_PAWN,NOCHESS,R_PAWN

16、,NOCHESS,R_PAWN,NOCHESS,R_PAWN,NOCHESS,R_PAWN,NOCHESS,R_CANON,NOCHESS,NOCHESS,NOCHESS,NOCHESS,NOCHESS,R_CANON,NOCHESS,NOCHESS,NOCHESS,NOCHESS,NOCHESS,NOCHESS,NOCHESS,NOCHESS,NOCHESS,NOCHESS,R_CAR,R_HORSE,R_ELEPHANT,R_BISHOP,R_KING,R_BISHOP,R_ELEPHANT,R_HORSE,R_CAR;图1 局面设计图棋子的定义:#define NOCHESS 0 /没有

17、棋子#define B_KING 1 /黑帅#define B_CAR 2 /黑车#define B_HORSE 3 /黑马#define B_CANON 4 /黑炮#define B_BISHOP 5 /黑士#define B_ELEPHANT 6 /黑象#define B_PAWN 7 /黑卒#define B_BEGIN B_KING#define B_END B_PAWN#define R_KING 8 /红将#define R_CAR 9 /红车#define R_HORSE 10/红马#define R_CANON 11/红炮#define R_BISHOP 12/红士#defin

18、e R_ELEPHANT 13/红相#define R_PAWN 14/红兵#define R_BEGIN R_KING#define R_END R_PAWN#define IsBlack(x) (x=B_BEGIN & x=R_BEGIN & x=R_END)/判断某个棋子是不是红色。/判断两个棋子是不是同色#define IsSameSide(x,y) (IsBlack(x) & IsBlack(y) | (IsRed(x) & IsRed(y)/棋子位置typedef struct BYTE x; BYTE y;CHESSMANPOS;5.3绘图部分对于绘图部分,主要实现的是程序界面的

19、绘图因此我们在这里将要完成棋盘、棋子的显示走棋起始位置和目标位置的提示框的显示。而要实现这些我们必须通过void CChessDlg:OnPaint() 这个函数实现void CChessDlg:OnPaint() CPaintDC dc(this); CDC MemDC; int i,j; POINT pt; CBitmap* pOldBmp; MemDC.CreateCompatibleDC(&dc); m_BoardBmp.LoadBitmap(IDB_CHESSBOARD); pOldBmp=MemDC.SelectObject(&m_BoardBmp); /绘制棋盘上的棋子 for(

20、i=0;i10;i+) for(j=0;j9;j+) if(m_byShowChessBoardij=NOCHESS) continue; pt.x=j*GRILLEHEIGHT+14; pt.y=i*GRILLEWIDTH+15; m_Chessman.Draw(&MemDC,m_byShowChessBoardij-1,pt,ILD_TRANSPARENT); /绘制用户正在拖动的棋子 if(m_MoveChess.nChessID!=NOCHESS) m_Chessman.Draw(&MemDC,m_MoveChess.nChessID-1,m_MoveChess.ptMovePoint

21、,ILD_TRANSPARENT); dc.BitBlt(0,0,m_nBoardWidth,m_nBoardHeight,&MemDC,0,0,SRCCOPY); /将绘制的内容刷新到屏幕 MemDC.SelectObject(&pOldBmp);/恢复内存Dc的原位图 MemDC.DeleteDC(); /释放内存 m_BoardBmp.DeleteObject(); /删除棋盘位图对象5.4鼠标响应部分鼠标响应部分包括LButtonDown和LButtonUp两个功能,LButtonDown实现的主要功能是拖动棋子在棋盘上的移动,他的重要性是,如果没有这个功能,将无法走棋,其函数实现通过

22、:void CChessDlg:OnLButtonDown(UINT nFlags, CPoint point) LButtonUp这个函数主要实现的功能是:拖动棋子完毕后放置到拖动后的位置,在进行放置的过程中,需要使用一个Drop的释放函数。函数实现通过:void CChessDlg:OnLButtonUp(UINT nFlags, CPoint point) 5.5棋子走法typedef struct short nChessID; /表明是什么棋子 CHESSMANPOS From;/起始位置 CHESSMANPOS To; /走到什么位置 int Score; /走法的分数CHESSM

23、OVE;在着法生成器中,采用的基本思想就是遍历整个棋盘(一个接一个地查看棋盘上的每个位置点),当发现有当前下棋方的棋子时先判断它是何种类型的棋子,然后根据其棋子类型而相应地找出其所有合法着法并存入着法队列。这里谈到的“合法着法”包括以下几点:1、各棋子按其行子规则行子。诸如马跳“日”字、象走“田”字、士在九宫内斜行等等(这里需要特别注意的是卒(兵)的行子规则会随其所在位置的不同而发生变化过河后可以左右平移)。2、行子不能越出棋盘的界限。当然所有棋子都不能走到棋盘的外面,同时某些特定的棋子还有自己的行棋界限,如将、士不能出九宫,象不能过河。3、行子的半路上不能有其它子阻拦(除了炮需要隔一个子才能

24、打子之外)以及行子的目的点不能有本方的棋子。4、将帅不能碰面(本程序中只在生成计算机的着法时认为将帅碰面是非法的,而对用户所走的导致将帅碰面的着法并不认为其非法,而只是产生败局罢了)。产生了着法后要将其存入着法队列以供搜索之用,由于搜索会搜索多层,所以在把着法存入着法队列的时候还要同时存储该着法所属的搜索层数。因此可以将着法队列定义为二维数组,其中第一个数组下标为层数,第二个数组下标为每一层的全部着法数。着法生成中的各个棋子走法以及其他规则代码见MoveGenerator.cpp。棋子的移动由以下的函数分别执行:帅(将):Void CMoveGenerator:Gen_KingMove()士:

25、红士void CMoveGenerator:Gen_RBishopMove()黑士void CMoveGenerator:Gen_BBishopMove()象:void CMoveGenerator:Gen_ElephantMove()马:void CMoveGenerator:Gen_HorseMove()车:void CMoveGenerator:Gen_CarMove()炮:void CMoveGenerator:Gen_CanonMove()兵(卒):红兵void CMoveGenerator:Gen_RPawnMove() 黑卒 void CMoveGenerator:Gen_BPa

26、wnMove()5.6搜索算法我们用一棵象棋树来表示下棋的过程:树中每一个结点代表棋盘上的一个局面,对每一个局面根据不同的走法又产生不同的局面。该象棋树包含三种类型的结点:奇数层的中间结点以及根结点,表示轮到红方走棋;偶数层的中间结点,表示轮到黑方走棋;叶子结点,表示棋局结束。结合上面所讲的树,若给每个结点都打一个分值来评价其对应的局面,我们通过估值引擎SetEveluator()来实现,过比较该分值的大小来判断局面的优劣。 void SetEveluator(CEveluation* pEval)m_pEval=pEval;假定甲乙两方下棋,甲胜的局面是一个极大值(一个很大的正数),那么乙胜

27、的局面就是一个极小值(极大值的负值),和棋的局面则是零值(或是接近零的值)。如此,当轮到甲走棋时他会尽可能地让局面上的分值大,相反轮到乙走棋时他会选尽可能地让局面上的分值小。反映到博弈树上,即如果假设奇数层表示轮到甲方走棋,偶数层表示轮到乙方走棋。那么由于甲方希望棋盘上的分值尽可能大,则在偶数层上会挑选分值最大的结点偶数层的结点是甲走完一步棋之后的棋盘局面,反映了甲方对棋局形势的要求。同样道理,由于乙方希望棋盘上的分值尽可能小,那么在奇数层上会选择分值最小的结点。这是“最小-最大”(Minimax)的基本思想。这样搜索函数在估值函数的协助下可以通过在奇数层选择分值最大(最小)的结点,在偶数层选

28、择分值最小(最大)的结点的方式来搜索以当前局面为根结点、限定搜索层数以内的整棵树来获得一个最佳的着法。下面是“最大-最小”的主要代码int CNegaMaxEngine:NegaMax(int nDepth) int current=-20000; int score; int Count,i; BYTE type; i=IsGameOver(CurPosition,nDepth);/检查棋局是否结束 if(i!=0) return i;/棋局结束,返回极大/极小值 if(nDepthEveluate(CurPosition,(m_nMaxDepth-nDepth)%2,m_nUserChes

29、sColor); /列举当前棋局下一步所有可能的走法 Count=m_pMG-CreatePossibleMove(CurPosition,nDepth,(m_nMaxDepth-nDepth)%2,m_nUserChessColor); if(nDepth=m_nMaxDepth) /在根节点设定进度条 m_pThinkProgress-SetRange(0,Count); m_pThinkProgress-SetStep(1); for(i=0;iStepIt();/走进度条 type=MakeMove(&m_pMG-m_MoveListnDepthi); /根据走法产生新局面 score=-NegaMax(nDepth-1); /递归调用负极大值搜索下一层节点 UnMakeMove(&m_pMG-m_MoveListnDepthi,type); /恢复当前局面 if(scorecurrent) /如果score大于

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1