基于mfc的对战象棋设计与实现毕设论文.docx
《基于mfc的对战象棋设计与实现毕设论文.docx》由会员分享,可在线阅读,更多相关《基于mfc的对战象棋设计与实现毕设论文.docx(50页珍藏版)》请在冰豆网上搜索。
基于mfc的对战象棋设计与实现毕设论文
毕业设计说明书
学生姓名
学号
学院
计算机科学与技术学院
专业
软件工程
题目
基于MFC的
对战象棋设计与实现
指导教师
(姓名)(专业技术职称/学位)
毕业论文独创性声明
本人郑重声明:
本论文是我个人在导师指导下进行的研究工作及取得的研究成果。
本论文除引文外所有实验、数据和有关材料均是真实的。
尽我所知,除了文中特别加以标注和致谢的地方外,论文中不包含其他人已经发表或撰写过的研究成果。
其他同志对本研究所做的任何贡献均已在论文中作了明确的说明并表示了谢意。
作者签名:
日期:
摘要:
中国象棋是我国历史悠久的智力对战游戏,发展至今已有数千年的历史,是中华民族智慧的结晶。
然而,传统象棋存在着棋盘单一、棋子收拾繁琐、下棋场地单一、无法及时找到对弈玩家几大弊端。
随着计算机技术的发展,电子版象棋游戏的诞生,很好的解决了这些问题。
本设计正是开发这样一款电子象棋游戏,它采用MFC文档视图体系结构和Visual C++开发工具,实现了具有背景棋盘和棋子种类的变换,走棋,悔棋,还原和网络对弈功能。
本设计还进行了画面闪烁消除,视觉效果更加人性化,且鼠标操作,简单易用,无须安装,即开即用。
关键词:
中国象棋,MFC文档视图,VisualC++,网络对弈,消除闪烁,即开即用
Abstract:
ChineseChessisourlonghistoryofintellectualbattlegame,thedevelopmenthasseveralthousandyearsofhistory,isthecrystallizationofthewisdomoftheChinesenation.However,thetraditionalchessthereisasingleboard,thepiecespackcumbersome,chessvenuessingle,notbeenabletofindseveralmajordrawbacksofthechessplayers.Withthedevelopmentofcomputertechnology,theelectronicversionofthebirthofachessgame,agoodsolutiontotheseproblems.
Thedesignisthedevelopmentofanelectronicchessgame,whichusesMFCdocumentviewarchitectureandVisualC++developmenttools,backgroundboardandpieceskindoftransformation,playingchess,undo,restore,andnetworkchessfunction.Thisdesignalsoflickeringeliminate,visualeffects,morehuman,mouseoperation,easytouse,noneedtoinstall.
Keywords:
Chinesechess,MFCdocumentview,VisualC++,networkgame,eliminateflicker,instantavailable
1绪论
1.1课题背景
随着时代的进步,电子技术日新月异的发展,单纯的户外实体游戏已经无法满足人们的需求,于是电子游戏诞生了,它创造出的虚拟游戏环境,帮助人们摆脱实体的束缚,更增添了游戏的趣味性。
计算机的发明,无疑使电子游戏又多了一个新的载体,带动其不断地创新、发展。
电脑游戏行业经过二十余年的发展,已成为与音乐、影视等并驾齐驱的全球最重要娱乐行业之一。
时下,与角色扮演类、即时战略类游戏相比,棋牌类游戏这种上手快、游戏时间短的传统游戏方式,仍在广大群众中占有举足轻重的地位。
其中方便、快捷、操作简单的棋类游戏,更是占主要位置。
作为中华民族悠久文化的代表之一,中国象棋不仅源远流长,而且基础广泛,作为一项智力运动,中国象棋开始走向世界。
为了方便其更好的推广,并且为了摆脱传统棋盘、棋子、场地的束缚,网络版象棋备受青睐,这也是本款象棋游戏开发的意义所在。
相信未来几年,象棋这一中国国粹在各个领域将得以推广,产生巨大影响。
1.2象棋简介
中国象棋历史悠久。
《楚辞•招魂》中有“蓖蔽象棋,有六簿些;分曹并进,遒相迫些;成枭而牟,呼五白些。
”。
《说苑》载:
雍门子周以琴见孟尝君,说:
“足下千乘之君也,……燕则斗象棋而舞郑女。
”由此可见,远在战国时代,象棋已在贵族阶层中流行开来了。
象棋属于二人对抗性游戏的一种,暗棋阁也是其中一种传统玩法,由于用具简单,趣味性强,成为流行极为广泛的棋艺活动。
象棋是我国正式开展的78个体育运动项目之一,为促进该项目在世界范围内的普及和推广,已将“中国象棋”项目名称更改为“象棋”。
此外,高材质的象棋也具有收藏价值,如:
高档木材、玉石等为材料的象棋。
更有文人墨客为象棋谱写了诗篇,使象棋更具有一种文化色彩。
1.2.1象棋棋盘
棋子活动的场所,叫作“棋盘”。
在长方形的平面上,共有九条平行的竖线和十条平行的横线,共有九十个交叉点。
棋盘两端的中间,也就是第四条到第六条竖线之间的正方形部位,有斜交叉线“米”字方格的地方,叫作“九宫”,象征着中军帐,是将和帅的驻扎地。
整个棋盘以“楚河●汉界”分为相等的两部分。
为了比赛记录和学习棋谱的统一,现在规则规定:
从右至左的九条竖线,用中文数字一至九来表示红方,用阿拉伯数字1至9来表示黑方。
己方的棋子始终使用己方的线路编号,无论棋子是否“过河”。
1.2.2象棋棋子
象棋是一种双方对弈的竞技项目。
棋子共有红黑16个,共32个棋子。
棋子种类说明如下表1-1:
表1-1棋子种类
红方名称
黑方名称
每方棋子数
活动范围
帅
将
1
本方九宫内
仕
士
2
本方九宫内(实际5个棋位)
相
象
2
本方区域内(实际7个棋位)
马
马
2
全盘任意位置
车
车
2
全盘任意位置
炮
炮
2
全盘任意位置
兵
卒
5
起始位置及前进一步的位置,敌方所有棋位
将与帅;士与仕;象与相;卒与兵的功能实际上完全相同,仅是为了区分黑红双方。
帅(将)是棋中的首脑,也是战术核心。
它只能在本方九宫之内活动,可上下左右沿着横线或者竖线移动一格。
帅与将不能在同一直线上直接对面,否则走方判负。
这个也就是判定函数ShuaiCanTo()实现的功能的依据。
仕(士)是将(帅)的贴身保镖,主要任务是防守,它也只能在九宫内走动,且只能斜走,不先后左右移动。
相(象)的主要作用也是防守,保护自己的帅(将)。
它的走法是每次沿对角线走两格,俗称“象飞田”。
相(象)的活动范围限于河界以内的本方阵地,不能过河,实际是7个特殊棋位,且若它走的田字中央有一个棋子,不管是对方还是本方棋子,都不能走,俗称“塞象眼”。
车在象棋中威力最猛,只要起始位置和目的位置中间没有其他棋子,它就可以到达它横竖线所在的任何地方。
俗称“一车十子寒”。
炮不吃子时,移动走法与车完全一样。
但当吃子时,它和目标棋子中间必须有一个且仅此一个棋子(无论己方或对方棋子)。
炮是象棋里面唯一一个可以越子的棋种,威力也很大。
马是先直后斜,即先直着走一格,然后再斜着走一个对角线,俗称“马走日”。
马一个可到周围八个点,故有“八面威风”之说。
但如果在要去的方向的第一步有别的棋子挡住,马就无法走过去,俗称“蹩马腿”和“塞象眼”类似。
兵(卒)不能后退且只能一步一步走,未过河前,只能向前。
过河以后,允许左右移动。
虽过河后只能一步一步走,但兵(卒)的威力也大大增强,故有“过河的卒子顶半个车”之说。
1.2.3术语[8]
(1)“马走日字,象飞田.车走直路,炮翻山.士走斜路护将边.小卒子一去不回还.车走直路马踏斜,相飞田子炮打隔,卒子过河了不得。
”
(2)“马后炮”:
泛指炮在马后,以马限制对方将帅的退路,兼以炮向对方叫将。
(3)“天地炮”:
一炮从中路牵制对方中士中象,另一炮从底线牵制对方底士底象。
(4)“铁门栓”:
以炮镇中路限制对方士象的活动,兼以车或兵(卒)守着对方的将(帅)门。
(5)“夹车炮”:
车炮或车双炮前后互相配合的一种战术。
(6)“炮碾丹沙”:
车炮在底线成将,从而杀去障碍(主要是士象)成杀势。
(7)“车炮抽杀”:
泛指炮在车后时,一面跳炮吃子,一面露车叫将,令对方顾此失彼的一种战术。
(8)“海底捞月”:
车炮或车兵在对方底线逼使对方将帅离开中路的一种战术。
(9)“两头蛇”:
把三路兵和七路兵挺起的阵式。
1.3MFC及相关技术
MFC:
微软基础类(MicrosoftFoundationClasses),C++是一种应用程序框架,随微软VisualC++开发工具一起发布。
该类库提供一组通用的可重用的类库供开发人员使用,大部分类均从CObject直接或间接派生,只有少部分类例外。
MFC应用程序的总体结构通常由开发人员从MFC类派生的几个类和一个CWinApp类对象(应用程序对象)组成。
MFC提供了MFCAppWizard自动生成框架。
Windows应用程序中,MFC的主包含文件为"Afxwin.h"。
此外MFC的部分类为MFC/ATL通用,可以在Win32应用程序中单独包含并使用这些类。
1.3.1单文档程序
1.应用类及全局对象(CChess_mApp)
应用类封装了Windows应用的初始化,运行以及终止的全过程。
对于每一个基于框架的应用,它必须有一个且只能有一个派生于CWinApp的类对象。
这个对象是全局对象,因此它在创建任何窗口前首先被构造。
类CWinApp提供了几个关键的可重载的虚成员函数,他们是InitInstance,Run,ExitInstance以及OnIdle等。
而且,在程序中可以随时调用全局函数AfxGetApp,以便获得CWinApp类对象的指针。
2.文档类(CChess_mDoc)
文档类实际上是一种数据结构,该类实现了对这种结构的封装以利于管理,通常,它不但包含应用中所需的数据,而且也包含了处理这些数据的方法,另外,文档类还可以为应用提供与其存储的数据相关的服务。
3.视图类(CChess_mView)
该类占有框架窗口的客户区,主要负责显示文档数据,也为文档对象和用户之间提供了用以交互的可视接口,另外,也完成了与文档打印相关的操作,通常,一般的绘制操作都是在该类中完成,因此有时也称视图类窗口为“绘制窗口”。
4.框架类(CMainFrame)
框架类表示应用程序的主框架窗口,其主要作用是响应标准的窗口消息,不过,它通常先将消息按照一定的次序传递给视图类以及文档类等其他命令处理类,另外,它还为视图类提供可视化的边框,同时也包括标题栏,一些标准的窗口组件等。
5.“关于”对话框类(CAboutDlg)
该类封装了用于显示软件版本,版权等相关信息的“关于”对话框,通常不需要对它进行任何的编程。
而只需要使用对话框资源编辑器对对话框模板进行简单的编辑即可。
1.3.2GDI绘图
GDI是GraphicsDeviceInterface的缩写,含义是图形设备接口,它的主要任务是负责系统与绘图程序之间的信息交换,处理所有Windows程序的图形输出。
在Windows操作系统下,绝大多数具备图形的的应用程序都离不开GDI,他们利用GDI所提供的众多函数可以方便地在屏幕,打印机及其他输出设备上输出图形、文本等。
GDI的出现时程序员无需关心硬件设备及设备驱动,就可以将应用程序的输出转化为硬件设备上的输出。
这实现了程序开发者与硬件设备的隔离,大大方便了开发工作。
想要在屏幕或者其他输出设备上输出图形或者文字,就必须先获得一个称为设备描述表(DC:
DeviceContext)的对象的句柄,以它为参考,调用各种GDI函数来实现各种文字或图形的输出。
设备描述表是GDI内部保存数据的一种数据结构,此结构中的属性内容与特定的输出设备(显示器、打印机等)相关,属性定义了GDI函数的工作细节。
属性包括文字的颜色及x坐标和y坐标映射到窗体显示区域的方式等。
一旦获得设备描述表的句柄,系统就是使用默认的属性值填充设备描述表结构。
如果有必要,可以使用一些GDI函数获得和改变设备描述表中的属性值。
绘图结束后必须释放设备描述表句柄。
GDI函数大致可分类为:
设备上下文函数(如GetDC、CreateDC、DeleteDC)、画线函数(如LineTo、Polyline、Arc)、填充画图函数(如Ellipse、FillRect、Pie)、画图属性函数(如SetBkColor、SetBkMode、SetTextColor)、文本、字体函数(如TextOut、GetFontData)、位图函数(如SetPixel、BitBlt、StretchBlt)、坐标函数(如DPtoLP、LPtoDP、ScreenToClient、ClientToScreen)、映射函数(如SetMapMode、SetWindowExtEx、SetViewportExtEx)、元文件函数(如PlayMetaFile、SetWinMetaFileBits)、区域函数(如FillRgn、FrameRgn、InvertRgn)、路径函数(如BeginPath、EndPath、StrokeAndFillPath)、裁剪函数(如SelectClipRgn、SelectClipPath)等。
1.3.3消息机制
MFC传输的消息有三种类型:
命令消息,控件通知和窗口消息。
命令消息一般与用户请求有关,当用户单击一个菜单项时,命令消息产生,并发送给能处理这个消息的类对象(如编辑文本等)。
控件消息在某些重要事件发送时,由控件窗口发送给父窗体处理,如打开一个对话框。
窗口消息(WindowMessage)一般与窗口的内部运作有关,如创建窗口消息WMPAINT和绘制窗口WMCREATE等。
通常,消息是从系统发送到窗口,或从窗口发送到窗口。
每个窗口使用窗口进程来处理发送给它的消息。
系统或应用程序有两种传输消息的方法:
发送消息或寄送消息。
鼠标和键盘消息一般是寄送消息,而所有其他消息通常都是发送消息。
发送消息时,直接调用窗口的窗口进程,通信是即时的,直到窗口进程为调用函数返回一个结果时,应用程序才能继续。
寄送消息时,把消息发送到拥有那个窗口的应用程序的消息队列中。
当应用程序空闲时,它会搜索消息队列,并处理优先级较高的消息,然后从队列中删除它,并把处理结果发送给既定窗口。
所以通信可能延迟。
在消息队列中,寄送的消息接受特殊的鼠标和键盘处理。
通常,应该尽量发送一个消息,除非想把动作延迟到所有鼠标和键盘消息被处理之后。
2概要设计
2.1设计思路分析
本程序采用MVC模式,将棋子信息与显示分离,统一由control控制。
棋盘用9*10的数组map存储(0~13表示各个棋子,14表为空),存储用于判断当前位置为何棋子或者空。
32个棋子由一个统一的棋子型CChess数组存储,统一管理显示。
每个棋子包含了自身的type,name,及其在棋盘中的位置x,y。
棋子走法是利用鼠标的消息处理函数,获得棋子种类,当前坐标和下一步坐标,共五个信息,再利用规定的CanGoTo()函数判断能否到达。
若能到达,则把当前棋子的坐标改为下一步坐标,并把棋盘中当前位置的map改为空,即表示无棋子。
如果下一步坐标的位置上有棋子,则将该棋子的type改为15,这样绘图时就不会显示该棋子的位图。
因为棋子位图周围有白色边框,通过“遮罩技术”可以消除边框,实现棋子透明覆在棋盘上,更具美感。
利用“内存DC双缓冲技术”消除闪烁,将棋盘和棋子信息一次性显示,并实现棋子黏在鼠标上,动态移动。
网络部分,继承MFC中的CAsyncSocket和CSocket进行开发。
Socket编程分为两种:
面向连接协议网络通信编程和面向无连接的网络通信编程。
本设计采用连接协议的Socket编程模型,保证网络上传输的数据及时、正确的到达。
2.2主要功能
通过计算机的鼠标键盘操作操作界面,必须按照象棋的规则进行对弈,如果在对弈过程中,一方出招错误,电脑会予以简单提示,并无视错误操作。
对弈过程中只能按照电脑预订顺序,即红先黑后的顺序依次出招,指导一方胜出,电脑显示哪方胜出为止。
1)可以采用鼠标操作进行对弈;
2)可以实现走棋、悔棋、还原、认输功能;
3)可以满足两人局域网内对弈;
4)可以在任意时间重新开始游戏;
5)可以进行简单错误判断,并直接返回到前一步棋子状态;
6)可以进行背景棋盘和棋子种类的变换;
7)可以实现自由设置棋谱(怪棋);
8)可以实现棋子黏在鼠标上移动,增加美感
2.3软件信息
1)软件名称:
基于MFC的局域网内对战象棋设计与实现
2)开发平台:
MicrosoftVisualC++6.0
3)用户:
象棋爱好者
4)本设计在各个方面均具有可行性,方便易用,无需安装即可使用
2.4流程图
(1)游戏交互图,如图2-1所示
图2-1游戏交互图
(2)程序流程图
首先,选择是否建立主机,否则为客户机。
若建立主机,则建立一个端口,用于和客户机的交互连接,然后等待知道有客户机连上。
客户机建立,则选择主机的ip地址和端口。
游戏双方先后点击开始,开始游戏。
红方、黑方在到自己状态时,可以移动自己的棋子,悔棋,还原,认输等等。
走棋,点击鼠标左键选中棋子,移动,放到想到达的地方,系统调用CanGoTo函数,判断是否可到,若可到,则棋子放到目的地,否则返回棋子原来的地方能够。
走棋成功后,发送消息给对方,对方接收消息后,进行相应的操作。
进行若干步之后,若帅或者将被吃掉,则判定胜负。
具体流程,见图2-2程序流程图。
图2-2程序流程图
3程序详细设计说明
3.1界面设计
本程序界面简单明了,包括棋盘显示,listbox,开始、悔棋、还原、认输四个按钮,还有用于聊天的edit和发送按钮。
菜单栏包括文件,控制,背景,帮助。
其中listbox是记录每步棋子走棋的信息和聊天信息,也是实现悔棋功能的一个重要存储器。
它是一个栈,可以记录,删除,提取每步棋子的信息。
悔棋操作可以从中得到相应的数据来实现悔棋功能。
文件内有新游戏、摆棋操作,控制内有悔棋、还原、认输操作,背景内有棋盘和棋子的切换操作。
主界面,如图3-1所示
图3-1主界面
3.1.1棋盘、棋子的位图载入与切换
(1)棋盘、棋子的位图载入
本设计实现了棋盘和棋子的自由无限制转换,采用了外部图片载入的方式,加载的位图,棋盘棋子一起加载,没有自己繁琐的自绘棋盘棋子过程。
本设计有6种棋盘,3种棋子可以搭配。
若程序在开始时就全部加载,会浪费大量内存,因为游戏过程中只需要一副棋盘棋子,且不利于更多棋盘和棋子种类的更新,也不利于后期维护。
故本程序采用外部图片载入的方式,载入棋盘棋子,每次切换调用SetBoardandPiece(CStringstrBoard,CStringstrPiece)重新对棋盘棋子的位图进行赋值。
strBoard,strPiece代表棋盘,棋子的存放文件夹相对物理地址。
HBITMAPCChess_mView:
:
LoadFileBmp(CStringfilePath)
{
Return(HBITMAP)LoadImage(AfxGetInstanceHandle(),filePath,IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
}
voidCChess_mView:
:
SetBoardandPiece(CStringstrBoard,CStringstrPiece)
{
//0红兵1红袍2红车3红马4红相5红士6红帅7黑兵8黑袍9黑车10黑马11黑象12黑士13黑将大于13不是棋子
ChessList[13]=LoadFileBmp(strPiece+"BK.BMP");
ChessList[12]=LoadFileBmp(strPiece+"BA.BMP");
ChessList[11]=LoadFileBmp(strPiece+"BB.BMP");
ChessList[10]=LoadFileBmp(strPiece+"BN.BMP");
ChessList[9]=LoadFileBmp(strPiece+"BR.BMP");
ChessList[8]=LoadFileBmp(strPiece+"BC.BMP");
ChessList[7]=LoadFileBmp(strPiece+"BP.BMP");
ChessList[6]=LoadFileBmp(strPiece+"RK.BMP");
ChessList[5]=LoadFileBmp(strPiece+"RA.BMP");
ChessList[4]=LoadFileBmp(strPiece+"RB.BMP");
ChessList[3]=LoadFileBmp(strPiece+"RN.BMP");
ChessList[2]=LoadFileBmp(strPiece+"RR.BMP");
ChessList[1]=LoadFileBmp(strPiece+"RC.BMP");
ChessList[0]=LoadFileBmp(strPiece+"RP.BMP");
ChessList[14]=LoadFileBmp(strPiece+"SEL.BMP");//光标位图
ChessList[15]=LoadFileBmp(strBoard);
ChessList[16]=LoadFileBmp(strPiece+"mask.bmp");//用于遮罩技术(见关键技术)
}
(2)棋盘、棋子的切换
当点击菜单栏背景的棋盘或者棋子,可以选择不同的棋盘和棋子。
减少玩家的视觉审美疲劳。
每按一个按钮,其实是改变了存放棋盘或棋子的函数SetBoardandPiece(CStringstrBoard,CStringstrPiece)中的strBoard或strPiece,即棋谱棋子的存放文件夹相对物理地址,完成了棋盘棋子的种类切换,并用Invalidate(FALSE)及时更新显示。
例如点击棋盘的水滴棋盘
voidCChess_mView:
:
OnDrop()
{
m_strBoard="res\\images\\drops.bmp";
SetBoardandPiece("res\\images\\drops.bmp",m_strPiece);
Invalidate(FALSE);
}
运行图,如图3-1所示:
图3-2棋盘、棋子的切换
3.1.2光标生成
双方局域网内对战,消息传递