首页 毕业论文-五子棋人机对弈系统设计

毕业论文-五子棋人机对弈系统设计

举报
开通vip

毕业论文-五子棋人机对弈系统设计毕业论文-五子棋人机对弈系统设计 题 目 五子棋人机对弈系统 英文题目 Five chess human-computer system 院 系 信息科学与技术学院 专 业 计算机科学与技术 姓 名 魏才江 年 级 2006级(A061228) 指导教师 周才学 二零一零年一月 摘 要 人工智能是一门正在迅速发展的新兴的,综合性很强的边缘科学。它与生物工程、空间技术一起被并列为二十一世界三大尖端技术。它的中心任务是研究如何使计算机去做那些过去只能靠人的智力才能做的工作。目前各发达国家都把人工智能作为重点列入...

毕业论文-五子棋人机对弈系统设计
毕业论文-五子棋人机对弈系统设计 题 目 五子棋人机对弈系统 英文题目 Five chess human-computer system 院 系 信息科学与技术学院 专 业 计算机科学与技术 姓 名 魏才江 年 级 2006级(A061228) 指导教师 周才学 二零一零年一月 摘 要 人工智能是一门正在迅速发展的新兴的,综合性很强的边缘科学。它与生物 工程 路基工程安全技术交底工程项目施工成本控制工程量增项单年度零星工程技术标正投影法基本原理 、空间技术一起被并列为二十一世界三大尖端技术。它的中心任务是研究如何使计算机去做那些过去只能靠人的智力才能做的工作。目前各发达国家都把人工智能作为重点列入本车的高科技发展 计划 项目进度计划表范例计划下载计划下载计划下载课程教学计划下载 当中,投入巨大的人力和物力。 计算机人机对弈也是其中之一。作为人智能研究的一个重要分支,计算机博弈是检验人工水平的一个重要方面。它的研究为人工智能带来了很多重要的方法和理论,产生了广泛的社会影响和学术影响。 五子棋人机对弈是计算机博弈中的一种。研究其计算机算法,可以让我们看到人工智能的初影,也有助于我们人脑的开发。五子棋是我国发明的,研究它可以让更多的外国人了解,有助于我国优秀文化的推广。 [关键词]:人工智能,计算人机对弈,五子棋,算法 I Abstract Artificial intelligence is a rapidly developing new, integrated a strong Frontier Science. It is with bio-engineering, space technology has been listed as 21 in the world along with the three cutting-edge technology. Its central task is to study how to make the computer do that in the past to rely on human intelligence to do. AI is currently regarded as the focus of the developed countries included in this car's high-tech development projects invested tremendous human and material resources. Man-machine chess computer is one of them. As a human study of an important branch of intelligence, the computer game to test the level of an important aspect of the manual. Its research in artificial intelligence has resulted in many important methods and theories to produce a wide range of social impact and academic impact. Man-machine chess game Renju in one of the computer. To study the computer algorithm, we can see the beginning of artificial intelligence shadow, but also help us to human brain development. Backgammon invented in China, and the research it can allow more foreigners to understand and help to promote China's traditional culture. [KeyWords] :Artificial intelligence , Man-machine chess computer , Man-machine chess,algorithm II 目 录 摘要„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„? Abstract„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„? 第一章 概述„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„1 1.1背景分析„„„„„„„„„„„„„„„„„„„„„„„„„„„1 1.2国内外现状„„„„„„„„„„„„„„„„„„„„„„„„„„2 第二章 需求分析„„„„„„„„„„„„„„„„„„„„„„„„„„„„3 2.1 需求分析„„„„„„„„„„„„„„„„„„„„„„„„„„3 2.2 性能需求„„„„„„„„„„„„„„„„„„„„„„„„„„3 2.3 系统平台需求„„„„„„„„„„„„„„„„„„„„„„„„3 2.4数据流图及数据字典„„„„„„„„„„„„„„„„„„„„„4 第三章 总体设计„„„„„„„„„„„„„„„„„„„„„„„„„„„„5 3.1 系统流程图„„„„„„„„„„„„„„„„„„„„„„„„5 3.2系统分析„„„„„„„„„„„„„„„„„„„„„„„„„„5 第四章 系统实现„„„„„„„„„„„„„„„„„„„„„„„„„„„„11 4.1界面实现„„„„„„„„„„„„„„„„„„„„„„„„„„11 4.2智能计算实现„„„„„„„„„„„„„„„„„„„„„„„„12 第五章 系统维护„„„„„„„„„„„„„„„„„„„„„„„„„„„30 5.1 系统测试„„„„„„„„„„„„„„„„„„„„„„„„„„30 5.2 系统维护„„„„„„„„„„„„„„„„„„„„„„„„„„31 第六章 总结„„„„„„„„„„„„„„„„„„„„„„„„„„„„„31 参考文献„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„33 致谢„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„„34 IV 第一章 概 述 当电脑进入我们的生活中,许多与相关学科都欣欣的向上发展。典型的有电子商务、电子邮件等。当然也有人智能了。人们在惊叹机器人高效的工作时,也会想起自己聪明的一面。人工智能也这方面也就深受我们喜爱。 1.1背景分析 五子棋是起源于中国古代的传统黑白棋种之一。现代五子棋日文称之为“连珠”,英译为“Ren-ju”,英文称之为“Gobang”或“FIR”(Five in a Row的缩写),亦有“连五子”、“五子连”、“串珠”、“五目”、“五目碰”、“五格”等多种称谓。五子棋不仅能增强思维能力,提高智力,而且变化多端,非常富有趣味性和消遣性,因此为人民群众所喜闻乐见。 另一方面,人工智能也在最近几年发展迅速。人们不断的研究出机器人之类的,使它能胜任人们能做的一些复杂的事,或是一些人们不适宜做的事,如水下探测等。而随着人们工作的加大,运动的时间也越来越少,大部分呆在家里或是工作的地方。这样人们就通过上网、购物等之类的事来取代生活中的不足。当然也有一部分群体在玩游戏之类的了。而五子棋由于其经典、易学等。深受人们的喜爱。人们在玩的同时也增加了自己的智慧。 1(任务提出 开发者:九江学院信息科学与技术学院 用户类型:各类棋牌游戏爱好者 用户特点:玩者只要了解五子棋的几条规则,能用基本的windows xp操作就能玩此系统。 2(系统目标 系统目标是总体设计的根据,是系统具体实现的前提,本系统将达到以下目标: (1) 便于一般懂五子棋群体。 (2) 便于新手玩 1 1.2 国内外现状 国内外研究五子棋的算法不少。有递归法、二叉树等。当然我所讨论的是一般的算了法。 无论何种算法,其大体遵循两条原则:1.使规则更加自然流畅,更容易被人接受。2.使棋的内容更加丰富多彩。而对于五子棋来说,所面临的困境归根结底是来自于其最本质的特点,也是目前一切规则的共同之处:连五终局(注意是连五终局而不一定是连五获胜,因为连五一方有可能违反长连禁手而被判负)。这个特点产生的结果就是使很多着法绝对化,从而极大地缩减了棋局的变化空间。当别的棋类中的棋子在大多数时间里都可以在棋盘上自由驰骋时,五子棋的棋子却经常为了应付对方的冲四和活三而不得不疲于奔命。 计算机对不同棋类研究程度的对比很能说明问题;对中象和国象的研究也足可匹敌人类中的顶尖高手;而对五子棋则动辄是“地毯终结”,以摧腐拉朽之势把这片领域中的未知之处一个又一个无情碾碎。不可否认这也是很多人认为五子棋“简单低级”的一个重要原因。面对这样的窘境,有的人提出一种大胆的设想,认为既然“连五终局”是造成五子棋变化简单的罪魁祸首,那么就应该将其摒弃,用其它的方法比如说看最后谁连五的数量更多来判定胜负。对于这样的想法,我认为大家应该以一种开放的心态去看待,即使是持反对态度,也要理解提出此类想法的人为了使五子棋更具活力,更加精彩而花费的心思,不要粗暴地给人家扣上一顶“荒诞不经”的帽子完事。 目前五子棋在规则方面遇到的困境不是简单采用某种现行规则,甚至不是对现行规则进行一些枝节上的修改能解决得了的。必须要有大胆的、飞跃性的变革才能使奄奄一息的五子棋有脱胎换骨的变化。至于具体的变革方式,我这个五子棋的门外汉怕是给不出什么像样的建议,还得靠你们这些内行来想办法。要说实现这一目标的具体 方案 气瓶 现场处置方案 .pdf气瓶 现场处置方案 .doc见习基地管理方案.doc关于群访事件的化解方案建筑工地扬尘治理专项方案下载 ,最好是能开一个全国乃至全世界范围内的规则统一大会,列举出几种切实可行的全新规则并经过充分讨论后,以投票方式选出最终的统一规则。也许有人觉得这个方案离现实太过遥远,不过我倒觉得此方案比统一于现有的有禁或无禁方案要现实可行的多,因为如果在目前某派所掌握的规则下实现统一,另一派会有严重的被欺压和被掠夺感,从而在心理上产生强烈的抗拒。 2 第二章 需求分析 2.1业务需求 1. 使用范围要求 该系统适于游戏爱好者。 2. 功能要求 该系统主要有以下功能: (1)玩家能与电脑下子 (2)适于新手来玩 2.2 性能需求 虽然系统不大,但要满足玩家的基本要求,电脑有一定的智能,能给于新手一定的帮助。 2.3 系统平台需求 1. 系统开发平台 操作系统:Windows xp系列 开发工具:Visual C++ 6.0 2. 开发环境介绍 Visual C++是Microsoft C/C++ 7.0之后推出的新一代程序开发工具,它不仅继承C++的特性,同时具备可视化程序语言(Visual Programming Language)及程序产生器的概念。既然是面向对象语言,当然会提供系统基础类给程序员再使用(Reuse)。在Visual C++ 中,延袭Microsoft C/C++7.0的作法,将原有的SDK函数重新封装在适 ”,当的类中,构造了“基础类函数库(Microsoft Foundation Class Library,简称MFC)它提供了许多现成的框架对象,可供在使用Visual C++设计应用程序是使用。此外,还提供“ClassWizard”与“AppWizard”可帮助构造基本的程序框架,从软件再使用的技术观点而言,已由SDK函数库方式经过面向对象程序设计方式进展到自动产生 模板 个人简介word模板免费下载关于员工迟到处罚通告模板康奈尔office模板下载康奈尔 笔记本 模板 下载软件方案模板免费下载 相关类程序代码方式(Framework)。 3 面向对象的程序设计是一种新型的程序设计方法,计算机环境本身就是一个对象的集合体,对象彼此之间通过消息相互作用,面向对象的程序设计提高了程序的模块化和可维护性。面向对象的程序设计有几个特点及优点。首先,由于对象包含属性和方法,因此支持模块化程序设计,而模块化程序设计支持开发的便利性及代码的可维护性。 Visual C++ 6.0是Microsoft公司推出的功能最强大、最复杂的语言产品之一,它是目前为止在Windows环境下进行大型软件开发的首选。其具有如下特点: (1)Visual C+ + 的语法符合ANSL C+ + 标准,并在此基础上针对Windows操作系统增加了一些语句; (2)集成了MFC(Microsoft Foundation Class)类库,MFC封装了Windows API函数和消息,使程序员可以使用MFC高效率地开发各种应用程序; (3)提供了MFC AppWizard,可方便地生成程序框架; (4)提供了基于MFC的ClassWizard,通过它可以轻松地完成对各种MFC类的使用与维护。 Visual C++ 6.0作为Visual Studio家族中的一员,是Microsoft公司以C++语言为基础开发的可视化集成开发工具,与其他编程语言Visual Basic 6.0、Visual ForPro等一起,成为广大程序员喜爱的开发平台。 2.4 数据流图及数据字典 由于此系统没有数据库,故没有数据流与数据字典。 4 第三章 总体设计 经过分析,对五子棋流程进行整理,得出其使用过程如下: 进入系统之后。玩家按F1开始游戏,首先是玩家下子,接着电脑下子。一直循环。在电脑或是玩家下了一个子后,电脑就计算一下,是否电脑获胜或玩家获胜或是和棋。若有一种情况出现,则暂停游戏显示出相应的结果。若玩家还想玩,继续按F1,若要退出则按F12。在游戏开始后,玩家可按F11进行智能提示。此按钮适于新手或是“作弊”的群体。 3.1 系统流程图 程序流程图如图3-1所示。首先看到的界面是我们熟悉的棋盘。可看到下面有一行文字。当用户按F1时,则游戏开始,这时用户先下子。电脑此时先根据算法计算下,是否和棋,是否电脑获胜,是否玩家获胜,若有一种情况发生,则进入暂停阶段,此时下子则无效,电脑显示相应的结果,否则电脑就根据自己的得分算法,计算出最佳位置。把电脑的子下到最好位置上。电脑下子了后,则电脑继续判断是否和棋,是否电脑获胜,是否玩家获胜,若有一种情况发生,同样进入到暂停阶段,显示相应的结果。若用户按了F12,则整个系统退出结束。若在开始后,又按了F11,则显示提示功能。这对于新手来说是很好的功能。 3.2系统分析 在看别人下棋时,我们常说一句“当局者迷,旁观者清”,但这句话对于AI所控制的计算机来说是不正确的。相反,计算机必须知道每回合的情况,能够知道有哪些获胜的方式,并计算出下一步棋的位置,判断当前的情况。 A:求得所有获胜的组合 首先,在一场五子棋的游戏中,计算机必须要知道有哪些获胜的组合,因此必须求得获胜的组合的总数,而求出总数后便可建立一个数组。可在游戏执行时判断胜负,这个概念比较复杂,我们可以在后面的代码中可看到。 我要做的是19X19的棋盘,获胜总数有点多。下面一一来讨论。(以表格作为棋盘,1表示为某一方的子,其中以(i,j)表示第i行第j列的格子,) 5 进入界面 Y N 开始游戏 当前界面 玩家下子 电脑下子 Y 和棋 Y 和棋 N 和棋 和棋 N Y 电脑获胜 Y 电脑获胜 N 电脑获胜 电脑获胜 N Y 玩家获胜 Y 玩家获胜 N 玩家获胜 N 玩家获胜 暂停并显示结果 N 退出 Y 3-1 退出游戏 6 1. 计算水平方向的获胜组合数 1 2 3 „„ 15 16 17 18 19 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 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可组成一个获胜组 7 合。总的获胜组合也是19X15=285种。 3. 计算正斜方向的获胜组合数 1 2 3 4 5 „„ 15 16 17 18 19 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 在第一行中,则可知(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种。 8 由前面的讨论中,我们可计算出19X19表格中五子棋的获胜种数。一共有285+285+225+225=1020种获胜方式。 B:建立一些相应的变量 对此我建立了一个数组,如下: BOOL cmp[19][19][1020]; //电脑的每一颗棋子是否在各个获胜组合中 BOOL ply[19][19][1020]; //电脑的每一颗棋子是否在各个获胜组合中 int wcount[2][1020]; //电脑与玩家在各个组合中的棋子个数 (三个变量的简写来源cmp:computer ply:player wcount:win count) 如上述讨论可知,对于电脑,若为正斜中的第一种情况,并假定为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表示玩家的子) 9 1 2 3 4 5 6 7 8 9 10 0 0 0 5 0 0 0 5 0 0 5 0 0 10 0 0 10 0 0 0 0 10 0 15 0 15 0 0 0 0 0 0 15 20 20 0 0 0 0 0 0 0 0 C P 0 0 0 0 0 0 0 15 20 20 0 0 0 0 0 0 10 0 15 0 15 0 0 0 0 5 0 0 10 0 0 10 0 0 0 0 0 0 5 0 0 0 5 0 0 0 0 0 0 0 0 0 0 0 0 如上表所示,为什么会出现在C左边为0而下面却为20分呢。 我们看下上面的表格就可知,C的左边有三个格,要想获胜,则必须再加上左右边的一个格了,而右边的一个格子被电脑占了,因此,此获胜组合中置为不可能,得分为0。而对于C下面的格子有四个获胜的组合,且每一种组合都可能获胜,因此每种组合的分数累加,可以得出其分数为20。因此在此棋盘中,最佳位置有四个。 以上是按每一种获胜组合为5分的来计算的。在每一次运行中,电脑都按些种算法,则电脑可以找到最佳的位置。 D:攻击与防守 经上述讨论可知,电脑一直在找自己一方的最佳位置。若玩家在某个时刻获胜了,电脑也在寻找自己的位置。如何才能解决这个问题呢,想想其实也不难。在下子的过程中,电脑还必须记下玩家的分数情况,并且计分方式要一样。每一次下完之后,电脑便计分,若是电脑的分数高,则下在已方,反之下在玩家的最佳位置。这样一来,电脑也就有了智能了。 10 第四章 系统实现 系统经过分析并加以设计,就可以着手进行实现了,本系统主要分为界面实现和算法实现。 4.1 界面的实现 本系统首先印入眼帘的是五子棋的界面。本系统的启动界面窗口如图4-1所示。 图4-1 利用MFC建立一个MFC工程。在mainFrame的析构函数中,插入下一句代码: 11 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。这个程序是用CClient dc(this)来取的。为了防止闪烁,我加了一个标记变量flagbj。初始值为0,加载背景之后就置为1。则可知,背景只显示一次。其代码如下: CBitmap bj; //存放背景图 CDC membj; //内存变量背景 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 智能算法实现 为了计算得分,在讨论之前要声明几个变量和几个函数。 int borad[19][19]; //五子棋盘的状态。0表示无棋,1表示为电脑的棋子, 12 2表示为玩家的棋子(borad) BOOL cmp[19][19][1020]; //电脑的获胜组合情况(computer) BOOL ply[19][19][1020]; //玩家的获胜组合情况(player) int wcount[2][1020]; //双方的组合情况中子的个数,wcount[0][1020]为 电脑,wcount[1][1020]为玩家(win count) int pscore[19][19]; //电脑的得分(player score) int cscore[19][19]; //玩家的得分(computer score) BOOL bcmp; //是否轮到电脑下棋(bool computer) BOOL bply; //是否轮到玩家下棋(bool computer) BOOL start; //游戏是否开始(start) BOOL pwin; //电脑是否获胜(player win) BOOL cwin; //玩家是否获胜(computer win) BOOL tie; //是否和棋(tie) BOOL tishi; //是否有智能提示(tishi) void initGame(); //初始化棋盘(initalite game) void countScore(); //计分函数(count score) void cmpTurn(); //电脑下子算法(computer turn) BOOL plyGame(); //是否玩家获胜(player game win) BOOL cmpGame(); //是否电脑获胜(computer game win) BOOL tieGame(); //是否为和棋(tie game) int topScore(); //查找最高分;返回最高分数(top score) //寻找电脑的随机位置并保存在mc,nc中(search count) void searchCount(int top,int countTep,int *mc,int *nc); int countTop(int top); //返回最高分的个数(count top score) 首先要进行初始化。先对棋盘及分数进行初始化。 //0表示无棋子,1表示为电脑的棋子,2表示为玩家的棋子 for(i=0;i<19;i++){ for(j=0;j<19;j++){ 13 pscore[i][j]=0; //玩家各得分为0 cscore[i][j]=0; //电脑各得分为0 borad[i][j]=0; //各空格置为无子 } } //各获胜组合中的棋子数为0 for(k=0;k<1020;k++){ wcount[0][k]=0; //电脑获胜组合数的个数 wcount[1][k]=0; //玩家获胜组合数的个数 } 然后要对获胜组合进行初始化。 //初始时各种获胜组合中的值都为false for(i=0;i<19;i++){ for(j=0;j<19;j++){ for(k=0;k<1020;k++){ cmp[i][j][k]=false; ply[i][j][k]=false; } } } //行的组合情况,count的初始值为0 for(i=0;i<19;i++){ for(j=0;j<15;j++){ for(k=0;k<5;k++){ cmp[i][j+k][count]=true; ply[i][j+k][count]=true; } count++; } 14 } //列的组合情况 for(i=0;i<15;i++){ for(j=0;j<19;j++){ for(k=0;k<5;k++){ cmp[i+k][j][count]=true; ply[i+k][j][count]=true; } count++; } } //正斜的组合情况 for(i=0;i<15;i++){ for(j=0;j<15;j++){ for(k=0;k<5;k++){ cmp[i+k][j+k][count]=true; ply[i+k][j+k][count]=true; } count++; } } //反斜的组合情况 for(i=0;i<15;i++){ for(j=18;j>=4;j--){ for(k=0;k<5;k++){ cmp[i+k][j-k][count]=true; ply[i+k][j-k][count]=true; } count++; } 15 } 进行初始化后,此时start、bply置为ture,bcmp置为false。即对每一种获胜组 合中的情况进行初始化。之后游戏开始,玩家可下子,电脑不可下子。先玩家下子, 转入到系统函数OnLButtonDown()。如下所示 void mainFrame::OnLButtonDown(UINT nFlags, CPoint point) { //玩家单击时的动作 if(start&&bply) { //若开始后且轮到玩家下子则进行判断 if(point.x>=38&&point.y&&point.x<=602&&point.y<=602) { mp=(int)floor((point.x-36)/30); np=(int)floor((point.y-36)/30); //空格才可下子 if(0==borad[mp][np]) { //置为玩家的子 borad[mp][np]=2; for(k=0;k<1020;k++){ //玩家子个数加1 if(-1!=wcount[1][k]&&ply[mp][np][k]) wcount[1][k]++; //电脑置为不可能获胜 if(cmp[mp][np][k]){ cmp[mp][np][k]=false; wcount[0][k]=-1; } } flaglb=1; //玩家下子了可以贴白子 与tishi中的flaglb形成合作关系 bply=false; //玩家不可下子 bcmp=true; //电脑可以下子 } } } 16 CFrameWnd::OnLButtonDown(nFlags, point); } 在此函数中,首先要判断下子的位置是否在五子棋的棋盘区域中。即使其成立point.x>=38&&point.y&&point.x<=602&&point.y<=602。若在区域中,就调用了系统中的函数floor(),用于对键单击时的位置取整,来得到单击进的位置。之后还要判断所下了位置是否是空子,若是空子才可下子。若为空,则此格即为玩家的子,borad[][]的值置为2(2表示为玩家的子)。玩家下子后,电脑的布局就要改变。这时对1020种获胜情况一一来进行讨论。若是玩家的子且在此获胜组合中有可能获胜,则wcount[1][]中的个数加一,若是电脑的获胜组合中也为true,则此时wcount[0][]置为-1,表示在此获胜组合中不可能获胜,并把对应的cmp[][][]的值置为false,表示电脑在此获胜组合中不可能获胜。玩家下完之后,此时就轮到电脑下子了。bply置为true,bcmp置为false,表示玩家下完之后是电脑下子。 玩家下完之后,这时就是轮到电脑下子。但在下子前判断下当前的状况。先贴子。 //玩家下完之后就重新贴子 for(i=0;i<19;i++){ for(j=0;j<19;j++){ //电脑为红子 if(1==borad[i][j]) dc.BitBlt(i*30+36,j*30+36,24,24,&memcs,0,0,SRCCOPY); // 玩家为绿子 if(2==borad[i][j]) dc.BitBlt(i*30+36,j*30+36,24,24,&memps,0,0,SRCCOPY); } } 刚刚玩家下完之后,只是内部的置为玩家的子,但是用户没有看到。此时若显示出来,则可了解到玩家的子确实下了。这时电脑就进入了计算阶段。这也是此系统的核心代码。此函数放置在OnTimer()中。如下所示: //是否和棋 tie=tieGame(); if(tie&&start) 17 { start=false; //游戏结束 bcmp=false; //电脑不可下子 bply=false; //玩家不档下子 MessageBox("朋友,水平不错,竟能与电脑和棋哦„„\n(按F1开始,F12 退出~)"); flagbj=0; //重新显示背景图片 } //是否电脑获胜 cwin=cmpGame(); if(cwin&&start) { start=false; //游戏结束 bcmp=false; //电脑不可下子 bply=false; //玩家不档下子 MessageBox("朋友,失败乃成功之母,请再接再励!\n(按F1开始,F12退 出~)"); flagbj=0; //重新显示背景图片 } //是否玩家获胜 pwin=plyGame(); if(pwin&&start) { start=false; //游戏结束 bcmp=false; //电脑不可下子 bply=false; //玩家不档下子 MessageBox("朋友,真牛~一下就赢了,要不收我作徒弟吧~~\n(按F1开 始,F12退出~)"); flagbj=0; //重新显示背景图片 } 先判断是否是和棋,若是则暂停程序。当然在此,判断和棋,我是调用了和棋的 函数tieGame()。其内容如下: BOOL mainFrame::tieGame(){ 18 //若有空格则不为和棋 for(i=0;i<19;i++){ for(j=0;j<19;j++){ if(0==borad[i][j]) { return false; } } } 若有一方胜也不为和棋 // for(k=0;k<1020;k++){ if(5==wcount[0][k]||5==wcount[1][k]) { return false; } } //否则为和棋 return true; } 要讨论19X19格了中的每一个格子。若每一个格子都不为空,即borad[][]!=0,并 且在获胜组合中没有一方获胜,则此时电脑即为和棋,返回true,否则都为false。这 样就可实现和棋的判断了。若是和棋,则此时start置为flase,表示游戏暂时停止。并 弹出对话框显示和棋。 若不为和棋,则判断是否是电脑获胜,其也调用判断电脑获胜的函数cmpGame(), 其内容如下: //是否玩家获胜 BOOL mainFrame::plyGame(){ for(k=0;k<1020;k++){ if(5==wcount[1][k]) //有五子棋相连则获胜 return true; } return false; 19 } 其实也挺容易的,只要看下wcount[1][]中是否有一种情况中的个数为5,若有此 时就返回true,否则返回flase。若是 电脑获胜,则也弹出对话框显示电脑获 胜。这之后便把start也置为false。 若电脑不获胜,则继续判断是否玩 家获胜,此时同样调用函数cmpGame() 来处理。如下所示: BOOL mainFrame::cmpGame(){ for(k=0;k<1020;k++){ if(5==wcount[0][k]) //有五子棋相连则获胜 return true; } return false; } 若在电脑的获胜组合中有一个组合的个数为5,则电脑获胜,这时就弹出对话框, 显示电脑获胜,游戏时放暂停状态。否则继续执行。 若玩家下子后没有和棋、电脑获胜或是玩家获胜,则此时就轮到电脑下子了。 首先统计下当前分数,看下当前的得分情况。如下: void mainFrame::countScore(){ for(i=0;i<19;i++){ for(j=0;j<19;j++){ //初始值为0 pscore[i][j]=0; cscore[i][j]=0; //若为空则计算分数 if(0==borad[i][j]) { //各种情况一一讨论 for(k=0;k<1020;k++){ 20 //若是玩家 if(ply[i][j][k]) { switch(wcount[1][k]) { case 0: //零个子情况 pscore[i][j]+=1; break; case 1: //一个子情况 pscore[i][j]+=5; break; case 2: //二个子情况 pscore[i][j]+=10; break; case 3: //三个子情况 pscore[i][j]+=30; break; case 4: //四个子情况 pscore[i][j]+=120; break; } } //若是电脑 if(cmp[i][j][k]) { switch(wcount[0][k]) { case 0: cscore[i][j]+=1; break; case 1: cscore[i][j]+=2; break; case 2: 21 cscore[i][j]+=8; break; case 3: cscore[i][j]+=32; break; case 4: cscore[i][j]+=128; break; } } } } } } } 对于19X19的格子,一一讨论。若格子为空,则进行统计,因为只有空格才可下 子。对于空格,对获胜的1020种情况一一讨论,若存在电脑的获胜组合为true,若组 合中已有一个子,则在此格中的分数加2,若是已有二个子,则数加8,三个的加32, 四个的加128。在此依据获胜组合中的棋子越多,则获胜的机会越大,分数也就越高, 计算机就按此分数来计算最佳位置。对于玩家的分数也用同样的规则。 统计完分之后,若是轮到电脑下子,游戏未结束,则电脑下子。 //是否轮到电脑下子 if(bcmp&start) cmpTurn(); 在此也调用了函数来处理电脑下子的算法。对于cmpTurn()的代码如下: void mainFrame::cmpTurn(){ //以下用于找到最高分 //最高分为0,tc为电脑的最高分,tp为玩家的最高分 tc=tp=0; 22 //标记位,0为没找到位置,1为有电脑下子的位置 int flag=0; for(i=0;i<19;i++){ for(j=0;j<19;j++){ //若是空格则统计分数 if(0==borad[i][j]) { if(pscore[i][j]>=tp) { mp=i; np=j; tp=pscore[i][j]; flag=1; } if(cscore[i][j]>=tc) { mc=i; nc=j; tc=cscore[i][j]; flag=1; } } } } //以下是电脑下了的位置 if(1==flag) { //若有电脑下子的位置才可下子 //玩家分数高,则下在玩家的最高分位置,否则下在电脑的最高分位置 if(tc=top) { top=pscore[i][j]; } if(cscore[i][j]>=top) { top=cscore[i][j]; } } } } //返回最高分数 return top; } 统计之后,再逐一进行讨论,若是最高分,则此即为当前的最佳位置。贴上白子,予以提示。当然若是这样的算法,也就是一般人的算法,我在此基础上加了下随机性。电脑的随机算法如下: void mainFrame::cmpTurn(){ int topc=topScore(); //得出最高分,临时存入到topc中 //找到最高分的个数,临时存入到countc中 int countc=countTopScore(topc); 26 int ranc=randomCount(countc); //返回0----countc-1中的一个随机数,用于增加难度 //找到最高分的随机位置,并保存到mc,nc中 searchCount(topc,ranc,&mc,&nc); „„„„„ } 在此,我所用的想法是,首先寻到最高分,即最佳位置,调用topScore()函数,然后找到最高分的个数,调用countTopScore(int topCount)函数,并存入到countc 1之间的随机数。 中,然后调用randomCount(countc)返回一个0到countc- int mainFrame::randomCount(int ran) { int tempc=0; tempc=(int)(1+ran*rand()/(RAND_MAX+1)); return tempc; } 接着调用searchCount(),找到最高分top中的随机位置countTep中的坐标并存入到mc,nc中。 void mainFrame::searchCount(int top,int countTep,int *mc,int *nc) { int tempc=0; //临时的个数 for(i=0;i<19;i++){ for(j=0;j<19;j++){ if(pscore[i][j]==top){ tempc++; //个数加1 if(tempc==countTep){ *mc=i; //电脑的X坐标 *nc=j; //电脑的Y坐标 return; } } if(cscore[i][j]==top){ 27 tempc++; if(tempc==countTep){ *mc=i; //电脑的X坐标 *nc=j; //电脑的Y坐标 return; } } } } } 到此整个系统也就完成了。 28 第五章 系统维护 5.1 系统测试 1(系统测试概述 系统测试是软件的一个重要的组成部分。软件测试在软件生命周期里横跨两个阶段。通常在编写出每个模块之后就对它做必要的测试。软件测试的目的与其它阶段的目的相反。软件测试的目的是发现错误。一般说来,测试不是由编写程序本人进行,它由专门的人员对它进行测试。软件一般有两种方法:黑盒测试和白盒测试。黑盒测试把程序看成一个黑盒子,完全不考虑程序的内部结构和处理过程。白盒测试是把程序看成一个透明的盒子里,也就是完全了解程序的结果和处理过程。软件测试过程一般分成以下几个步骤: 模块测试:保证每个模块作为一个单元能正确运行,所以模块测试通常 称为单元测试。在这个测试步骤中所发现的往往是编码和详细设计的错误。 子系统测试:把经过单元测试的模块放在一起形成一个子系统来测试。模块相互间的协调和通信是这个测试过程中的主要问题,因此这个步骤着重测试模块的接口。 系统测试:把经过测试的子系统装配成一个完整的系统来测试。 验收测试:把软件系统作为单一的实体进行测试,要用户参与。目的是验证系统确实能够满足用户的需要,在这个测试步骤中发现的往往是系统需求说明 关于书的成语关于读书的排比句社区图书漂流公约怎么写关于读书的小报汉书pdf 中的错误。 平行测试:同时运行新开发出来的系统和将被它取代的旧系统,以便比较新旧两个系统的处理结果。 本系统使用黑盒子法进行测试。下面就输入一些信息,看能不能输出相应正确的结果。 2(系统测试 刚进入系统时,单击左键,此时系统无反应,表示游戏还未开始。若按下F1则弹出的对话框,玩家可以单击,但要是单击在五子棋的表格外,则不起作用。若在区域 29 内,可以下子。若单击时下有子,则不予响应。若某一方有五子连棋时,此时会出现相应的对话框。若按下F11时,此时会弹出智能提示对话框,并在当前最佳位置贴上白子。若按下F12时,此时系统弹出一个退出对话框,单击之后系统便退出。 根据测试结果分析,测试数据与理论数据一致,能达到预期效果,该系统运行正常。 5.2 系统维护 因为软件测试不可能暴露出软件系统中所有潜藏的错误,所以必然要进行维护。维护阶段是软件生存周期中时间最长的一个阶段,所花费的精力和费用也是最多的一个阶段。在以后应用阶段,随着环境的变化,要对程序进行变动。所以提高软件的可维护性也是必要的。 30 第六章 总 结 通过独立完成五子棋对弈系统的后,发现自己在进行软件开发方面提高不少,同时积极利用所学到的新技术用于自己的设计开发过程。另外,在整个开发的过程中,时间也比较仓促。因此,该系统必然会存在一些缺陷和不足。如:没有讨论五子棋禁手的问题。另一个就是电脑按即定的算法去与玩家下子。这种算法有点“固定”。不太会变,玩家若是仔细观察,可以掌握其规律。还有就是界面不是很华丽。有待改进。 尽管本系统存在着很多不足,但其实现了最重要的功能就是有人工智能。这也让我对计算机中的人工智能领域有一定的了解。另一个就是在做系统的过程中,我学到了Visual C++的一些基本结构,尤其对于MFC有一定的了解。还有就是对于C++有更深一步的认识。 31 参考文献 [1] Visual C++游戏设计入门. 机械工业出版社 普悠玛数科技 著 [2] 标准C++实用教程. 电子工业出版社 康晓明 汪涛 等编著 [3] 深入浅出MFC第2版. 华中科技大学出版社 侯俊杰 著 [4] C++面向对象程序设计 中国铁道出版社 谭浩强,陈维兴,林小茶. [5] 张海藩,牟永敏.面向对象程序设计实用教程.北京:清华大学出版社 [6] Visual C++项目开发实践.李强 贾云霞编著 中国铁道出版社 [7]Visual C++编程疑难详解——钱新贤 杨猛 程兆炜 张少东编著 人民邮电出版社 [8]Visual C++6.0实用编程技术——席庆 张春林编著 中国水利水电出版社 [9]Visual C++ 游戏设计入门——普悠玛数位科技编著 机械工业出版社 [10]C++面向对象程序设计——陈维兴 林小茶编著 中国铁道出版社 [11]五子棋制胜妙谱——章照原编著 [12]《连珠五子棋电视讲座》——作者:那威,彭建国主讲;中央电视台体育部编 [13]初级职业连珠五子棋 廿四种开局——作者:彭建国,那 威编著 [14]连珠五子棋入门——作者:彭建国,那威著 [15]五子连珠十日通——作者:那威,彭建国编著 [16]五子棋必读—— 作者:彭建国编 [17]连珠五子棋快速入门——作者:刘得新编 32 致 谢 在论文即将完成之际,本人在此向所有关心我的及帮助我的老师和同学们致以最真诚的感谢。 在本次毕业设计中,我从指导老师--------周老师,身上学到了很多东西。他认真负责的工作态度,严谨的治学精神和深厚的理论水平都使我收益匪浅。他无论在理论上还是在实践中,都给与我很大的帮助,使我得到很大的提高,这对于我以后的工作和学习都有一种巨大的帮助,在此感谢他耐心的辅导。在撰写论文阶段,周老师几次审阅我们的论文,提出了许多宝贵意见,没有他的指导,我们就不能较好的完成课题设计的任务。 另外,我还要感谢在这几年来对我有所教导的老师,他们孜孜不倦的教诲不但让我学到了很多知识,而且让我掌握了学习的方法,更教会了我做人处事的道理,在此表示感谢。同时,在系统开发过程中还有同组的同学也给了我不少帮助,这里一并表示感谢。 33 34 35 36
本文档为【毕业论文-五子棋人机对弈系统设计】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_882336
暂无简介~
格式:doc
大小:139KB
软件:Word
页数:41
分类:生活休闲
上传时间:2017-09-27
浏览量:19