计科091 姚伟小组 五子棋游戏设计Word下载.docx
《计科091 姚伟小组 五子棋游戏设计Word下载.docx》由会员分享,可在线阅读,更多相关《计科091 姚伟小组 五子棋游戏设计Word下载.docx(29页珍藏版)》请在冰豆网上搜索。
第六章总结……………………………………………………………………………31
参考文献…………………………………………………………………………………33
致谢………………………………………………………………………………………34
第一章概述
当电脑进入我们的生活中,许多与相关学科都欣欣的向上发展。
典型的有电子商务、电子邮件等。
当然也有人智能了。
人们在惊叹机器人高效的工作时,也会想起自己聪明的一面。
人工智能也这方面也就深受我们喜爱。
1.1背景分析
五子棋是起源于中国古代的传统黑白棋种之一。
现代五子棋日文称之为“连珠”,英译为“Ren-ju”,英文称之为“Gobang”或“FIR”(FiveinaRow的缩写),亦有“连五子”、“五子连”、“串珠”、“五目”、“五目碰”、“五格”等多种称谓。
五子棋不仅能增强思维能力,提高智力,而且变化多端,非常富有趣味性和消遣性,因此为人民群众所喜闻乐见。
另一方面,人工智能也在最近几年发展迅速。
人们不断的研究出机器人之类的,使它能胜任人们能做的一些复杂的事,或是一些人们不适宜做的事,如水下探测等。
而随着人们工作的加大,运动的时间也越来越少,大部分呆在家里或是工作的地方。
这样人们就通过上网、购物等之类的事来取代生活中的不足。
当然也有一部分群体在玩游戏之类的了。
而五子棋由于其经典、易学等。
深受人们的喜爱。
人们在玩的同时也增加了自己的智慧。
1.任务提出
开发者:
九江学院信息科学与技术学院
用户类型:
各类棋牌游戏爱好者
用户特点:
玩者只要了解五子棋的几条规则,能用基本的windowsxp操作就能玩此系统。
2.系统目标
系统目标是总体设计的根据,是系统具体实现的前提,本系统将达到以下目标:
(1)便于一般懂五子棋群体。
(2)便于新手玩
1.2国内外现状
国内外研究五子棋的算法不少。
有递归法、二叉树等。
当然我所讨论的是一般的算了法。
无论何种算法,其大体遵循两条原则:
1.使规则更加自然流畅,更容易被人接受。
2.使棋的内容更加丰富多彩。
而对于五子棋来说,所面临的困境归根结底是来自于其最本质的特点,也是目前一切规则的共同之处:
连五终局(注意是连五终局而不一定是连五获胜,因为连五一方有可能违反长连禁手而被判负)。
这个特点产生的结果就是使很多着法绝对化,从而极大地缩减了棋局的变化空间。
当别的棋类中的棋子在大多数时间里都可以在棋盘上自由驰骋时,五子棋的棋子却经常为了应付对方的冲四和活三而不得不疲于奔命。
计算机对不同棋类研究程度的对比很能说明问题;
对中象和国象的研究也足可匹敌人类中的顶尖高手;
而对五子棋则动辄是“地毯终结”,以摧腐拉朽之势把这片领域中的未知之处一个又一个无情碾碎。
不可否认这也是很多人认为五子棋“简单低级”的一个重要原因。
面对这样的窘境,有的人提出一种大胆的设想,认为既然“连五终局”是造成五子棋变化简单的罪魁祸首,那么就应该将其摒弃,用其它的方法比如说看最后谁连五的数量更多来判定胜负。
对于这样的想法,我认为大家应该以一种开放的心态去看待,即使是持反对态度,也要理解提出此类想法的人为了使五子棋更具活力,更加精彩而花费的心思,不要粗暴地给人家扣上一顶“荒诞不经”的帽子完事。
目前五子棋在规则方面遇到的困境不是简单采用某种现行规则,甚至不是对现行规则进行一些枝节上的修改能解决得了的。
必须要有大胆的、飞跃性的变革才能使奄奄一息的五子棋有脱胎换骨的变化。
至于具体的变革方式,我这个五子棋的门外汉怕是给不出什么像样的建议,还得靠你们这些内行来想办法。
要说实现这一目标的具体方案,最好是能开一个全国乃至全世界范围内的规则统一大会,列举出几种切实可行的全新规则并经过充分讨论后,以投票方式选出最终的统一规则。
也许有人觉得这个方案离现实太过遥远,不过我倒觉得此方案比统一于现有的有禁或无禁方案要现实可行的多,因为如果在目前某派所掌握的规则下实现统一,另一派会有严重的被欺压和被掠夺感,从而在心理上产生强烈的抗拒。
第二章需求分析
2.1业务需求
1.使用范围要求
该系统适于游戏爱好者。
2.功能要求
该系统主要有以下功能:
(1)玩家能与电脑下子
(2)适于新手来玩
2.2性能需求
虽然系统不大,但要满足玩家的基本要求,电脑有一定的智能,能给于新手一定的帮助。
2.3系统平台需求
1.系统开发平台
操作系统:
Windowsxp系列
开发工具:
VisualC++6.0
2.开发环境介绍
VisualC++是MicrosoftC/C++7.0之后推出的新一代程序开发工具,它不仅继承C++的特性,同时具备可视化程序语言(VisualProgrammingLanguage)及程序产生器的概念。
既然是面向对象语言,当然会提供系统基础类给程序员再使用(Reuse)。
在VisualC++中,延袭MicrosoftC/C++7.0的作法,将原有的SDK函数重新封装在适当的类中,构造了“基础类函数库(MicrosoftFoundationClassLibrary,简称MFC)”,它提供了许多现成的框架对象,可供在使用VisualC++设计应用程序是使用。
此外,还提供“ClassWizard”与“AppWizard”可帮助构造基本的程序框架,从软件再使用的技术观点而言,已由SDK函数库方式经过面向对象程序设计方式进展到自动产生模板相关类程序代码方式(Framework)。
面向对象的程序设计是一种新型的程序设计方法,计算机环境本身就是一个对象的集合体,对象彼此之间通过消息相互作用,面向对象的程序设计提高了程序的模块化和可维护性。
面向对象的程序设计有几个特点及优点。
首先,由于对象包含属性和方法,因此支持模块化程序设计,而模块化程序设计支持开发的便利性及代码的可维护性。
VisualC++6.0是Microsoft公司推出的功能最强大、最复杂的语言产品之一,它是目前为止在Windows环境下进行大型软件开发的首选。
其具有如下特点:
(1)VisualC++的语法符合ANSLC++标准,并在此基础上针对Windows操作系统增加了一些语句;
(2)集成了MFC(MicrosoftFoundationClass)类库,MFC封装了WindowsAPI函数和消息,使程序员可以使用MFC高效率地开发各种应用程序;
(3)提供了MFCAppWizard,可方便地生成程序框架;
(4)提供了基于MFC的ClassWizard,通过它可以轻松地完成对各种MFC类的使用与维护。
VisualC++6.0作为VisualStudio家族中的一员,是Microsoft公司以C++语言为基础开发的可视化集成开发工具,与其他编程语言VisualBasic6.0、VisualForPro等一起,成为广大程序员喜爱的开发平台。
2.4数据流图及数据字典
由于此系统没有数据库,故没有数据流与数据字典。
第三章总体设计
经过分析,对五子棋流程进行整理,得出其使用过程如下:
进入系统之后。
玩家按F1开始游戏,首先是玩家下子,接着电脑下子。
一直循环。
在电脑或是玩家下了一个子后,电脑就计算一下,是否电脑获胜或玩家获胜或是和棋。
若有一种情况出现,则暂停游戏显示出相应的结果。
若玩家还想玩,继续按F1,若要退出则按F12。
在游戏开始后,玩家可按F11进行智能提示。
此按钮适于新手或是“作弊”的群体。
3.1系统流程图
程序流程图如图3-1所示。
首先看到的界面是我们熟悉的棋盘。
可看到下面有一行文字。
当用户按F1时,则游戏开始,这时用户先下子。
电脑此时先根据算法计算下,是否和棋,是否电脑获胜,是否玩家获胜,若有一种情况发生,则进入暂停阶段,此时下子则无效,电脑显示相应的结果,否则电脑就根据自己的得分算法,计算出最佳位置。
把电脑的子下到最好位置上。
电脑下子了后,则电脑继续判断是否和棋,是否电脑获胜,是否玩家获胜,若有一种情况发生,同样进入到暂停阶段,显示相应的结果。
若用户按了F12,则整个系统退出结束。
若在开始后,又按了F11,则显示提示功能。
这对于新手来说是很好的功能。
3.2系统分析
在看别人下棋时,我们常说一句“当局者迷,旁观者清”,但这句话对于AI所控制的计算机来说是不正确的。
相反,计算机必须知道每回合的情况,能够知道有哪些获胜的方式,并计算出下一步棋的位置,判断当前的情况。
A:
求得所有获胜的组合
首先,在一场五子棋的游戏中,计算机必须要知道有哪些获胜的组合,因此必须求得获胜的组合的总数,而求出总数后便可建立一个数组。
可在游戏执行时判断胜负,这个概念比较复杂,我们可以在后面的代码中可看到。
我要做的是19X19的棋盘,获胜总数有点多。
下面一一来讨论。
(以表格作为棋盘,1表示为某一方的子,其中以(i,j)表示第i行第j列的格子,)
1.计算水平方向的获胜组合数
123……1516171819
1
可以看到对于第一行中(1,1),(1,2),(1,3),(1,4),(1,5)这五个格可以是一个获胜组合,而(1,2),(1,3),(1,4),(1,5),(1,6)这五个格子也可以组成一个获胜组合。
这样一直到最后一种为(1,15),(1,16),(1,17),(1,18),(1,19)这五个格子组成一个获胜组合。
即第一行有15种获胜的组合。
总的有19行。
可得,对于行中,我们有19X15=285种获胜组合。
2.计算垂直方向的获胜组合数
同理对于垂直的获胜组合中第一种为第一列的1,2,3,4,5可组成一个获胜组合。
总的获胜组合也是19X15=285种。
3.计算正斜方向的获胜组合数
12345……1516171819
在第一行中,则可知(1,1),(2,2),(3,3),(4,4),(5,5)为一获胜组合,而(1,3),(2,4),(3,5),(4,6),(5,7)也是一种获胜组合。
第一行中的最后一种为(1,15),(2,16),(3,17),(4,18),(5,19)。
总的获胜组合有15种,而最后一行i只能到15。
这样我们可以计算得到正斜有15X15=225种。
4.计算反斜方向的获胜组合数
依据上一种正斜,同理可推知反斜也有15X15=225种。
由前面的讨论中,我们可计算出19X19表格中五子棋的获胜种数。
一共有285+285+225+225=1020种获胜方式。
B:
建立一些相应的变量
对此我建立了一个数组,如下:
BOOLcmp[19][19][1020];
//电脑的每一颗棋子是否在各个获胜组合中
BOOLply[19][19][1020];
intwcount[2][1020];
//电脑与玩家在各个组合中的棋子个数
(三个变量的简写来源cmp:
computerply:
playerwcount:
wincount)
如上述讨论可知,对于电脑,若为正斜中的第一种情况,并假定为1020种获胜组合中的第570种获胜组合。
则其数组元素值设定如下:
cmp[0][0][570]=true;
cmp[0][1][570]=flase;
cmp[0][2][570]=false;
……
cmp[1][0][570]=false;
cmp[1][1][570]=true;
cmp[1][2][570]=false;
cmp[2][2][570]=true;
cmp[3][3][570]=true;
cmp[4][4][570]=true;
ply[][][]数组元素的初始化与cmp[][][]是相同的,但若在程序执行时,若玩家的棋占了(0,0)的位置,那么电脑在cmp[0][0][570]元素就会置为false,因为计算机就不可能再下到(0,0)上,因此第570种方法中对电脑来说是不可能的情况了。
同理,对于若是电脑占了(0,0)的位置,则玩家中此获胜组合中也置为不可能。
wcount[2][1020]用来记录玩家或计算机在各自的获胜组合中棋子的个数。
其中wcount[0][]来计算电脑的个数,wcount[1][]用来计算玩家的个数。
假如在第570种获胜组合中填入了3个电脑的子,则此时则有wcount[0][570]=3。
若在某一时刻有wcount[][]=5,则此时即可判定某一方获胜了。
C:
分数的设定
组在游戏中,为了让电脑找到最佳的走法,必须计算出电脑下到棋盘中任一格的分数,其中最高分即是电脑下的位置。
如下表所示,为了讨论方便,我只画了一个10X10的表格(其中C表示电脑的子,P表示玩家的子)
12345678910
5
10
15
20
C
P
如上表所示,为什么会出现在C左边为0而下面却为20分呢。
我们看下上面的表格就可知,C的左边有三个格,要想获胜,则必须再加上左右边的一个格了,而右边的一个格子被电脑占了,因此,此获胜组合中置为不可能,得分为0。
而对于C下面的格子有四个获胜的组合,且每一种组合都可能获胜,因此每种组合的分数累加,可以得出其分数为20。
因此在此棋盘中,最佳位置有四个。
以上是按每一种获胜组合为5分的来计算的。
在每一次运行中,电脑都按些种算法,则电脑可以找到最佳的位置。
D:
攻击与防守
经上述讨论可知,电脑一直在找自己一方的最佳位置。
若玩家在某个时刻获胜了,电脑也在寻找自己的位置。
如何才能解决这个问题呢?
想想其实也不难。
在下子的过程中,电脑还必须记下玩家的分数情况,并且计分方式要一样。
每一次下完之后,电脑便计分,若是电脑的分数高,则下在已方,反之下在玩家的最佳位置。
这样一来,电脑也就有了智能了。
第四章系统实现
系统经过分析并加以设计,就可以着手进行实现了,本系统主要分为界面实现和算法实现。
4.1界面的实现
本系统首先印入眼帘的是五子棋的界面。
本系统的启动界面窗口如图4-1所示。
图4-1
利用MFC建立一个MFC工程。
在mainFrame的析构函数中,插入下一句代码:
Create(NULL,"
五子棋"
WS_OVERLAPPEDWINDOW&
~WS_SIZEBOX&
~WS_MAXIMIZEBOX,CRect(0,0,700,700),NULL,NULL,0,NULL);
则此窗口生成的标题为“五子棋”,当加入了WS_SIZEBOX与WS_MAXIMIZEBOX后,此窗口就不能最大化显示且不能调整边框大小,即一创建的框架为不可改变的大小,另一个为CRect(0,0,700,700)。
此框架的大小为700X700。
窗口创建后就是导入图片。
为此首先导入图片到工程中,命名为IDB_BJ。
要导入一张图片需要三个步骤。
先要取得设备的DC。
这个程序是用CClientdc(this)来取的。
为了防止闪烁,我加了一个标记变量flagbj。
初始值为0,加载背景之后就置为1。
则可知,背景只显示一次。
其代码如下:
CBitmapbj;
//存放背景图
CDCmembj;
//内存变量背景
membj.CreateCompatibleDC(&
dc);
//创建相容的内存变量
bj.LoadBitmap(IDB_BJ);
//加载背景图
membj.SelectObject(&
bj);
//选择背景图
//初始时只需显示一次背景就可
if(0==flagbj){
//若是左键单击了之后才可重新绘图,目的是白子只重新绘制一次
if(1==flaglb){
dc.BitBlt(0,0,700,700,&
membj,0,0,SRCCOPY);
}
//置为1表示不再显示背景
flagbj=1;
}
4.2智能算法实现
为了计算得分,在讨论之前要声明几个变量和几个函数。
intborad[19][19];
//五子棋盘的状态。
0表示无棋,1表示为电脑的棋子,2表示为玩家的棋子(borad)
BOOLcmp[19][19][1020];
//电脑的获胜组合情况(computer)
BOOLply[19][19][1020];
//玩家的获胜组合情况(player)
intwcount[2][1020];
//双方的组合情况中子的个数,wcount[0][1020]为电脑,wcount[1][1020]为玩家(wincount)
intpscore[19][19];
//电脑的得分(playerscore)
intcscore[19][19];
//玩家的得分(computerscore)
BOOLbcmp;
//是否轮到电脑下棋(boolcomputer)
BOOLbply;
//是否轮到玩家下棋(boolcomputer)
BOOLstart;
//游戏是否开始(start)
BOOLpwin;
//电脑是否获胜(playerwin)
BOOLcwin;
//玩家是否获胜(computerwin)
BOOLtie;
//是否和棋(tie)
BOOLtishi;
//是否有智能提示(ti