实验二:利用α-β搜索过程的博弈树搜索算法编写一字棋游戏.doc

上传人:cl****1 文档编号:548402374 上传时间:2024-02-15 格式:DOC 页数:13 大小:189.50KB
返回 下载 相关 举报
实验二:利用α-β搜索过程的博弈树搜索算法编写一字棋游戏.doc_第1页
第1页 / 共13页
实验二:利用α-β搜索过程的博弈树搜索算法编写一字棋游戏.doc_第2页
第2页 / 共13页
实验二:利用α-β搜索过程的博弈树搜索算法编写一字棋游戏.doc_第3页
第3页 / 共13页
实验二:利用α-β搜索过程的博弈树搜索算法编写一字棋游戏.doc_第4页
第4页 / 共13页
实验二:利用α-β搜索过程的博弈树搜索算法编写一字棋游戏.doc_第5页
第5页 / 共13页
点击查看更多>>
资源描述

《实验二:利用α-β搜索过程的博弈树搜索算法编写一字棋游戏.doc》由会员分享,可在线阅读,更多相关《实验二:利用α-β搜索过程的博弈树搜索算法编写一字棋游戏.doc(13页珍藏版)》请在金锄头文库上搜索。

1、实验二:利用-搜索过程的博弈树搜索算法编写一字棋游戏一、实验目的与要求(1)了解极大极小算法的原理和使用方法,并学会用-剪枝来提高算法的效率。(2)使用C语言平台,编写一个智能井字棋游戏。(3)结合极大极小算法的使用方法和-剪枝,让机器与人对弈时不但有智能的特征,而且计算的效率也比较高。二、实验原理一字棋游戏是一个流传已久的传统游戏。游戏由两个人轮流来下,分别用“X”和“O”来代替自身的棋子。棋盘分9个格,双方可以在轮到自己下的时候,可以用棋子占领其中一个空的格子。如果双方中有一方的棋子可以连成一条直线,则这一方判胜,对方判负。当所有的格子都被占领,但双方都无法使棋子连成一条直线的话,则判和棋

2、。这是一个智能型的一字棋游戏,机器可以模拟人与用户对弈。当轮到机器来下的时候,机器会根据当前棋局的形势,利用极大极小算法算出一个评价值,判断如何下才对自身最有利,同时也是对方来说对不利的,然后下在评价值最高的地方。另外利用-剪枝,使机器在搜索评价值的时候不用扩展不必要的结点,从而提高机器计算的效率。在用户界面方法,用一个33的井字格来显示用户与机器下的结果。当要求用户输入数据的时候会有提示信息。用户在下的过程中可以中途按下“0”退出。当用户与计算机分出了胜负后,机器会显示出比赛的结果,并按任意键退出。如果用户在下棋的过程中,输入的是非法字符,机器不会做出反应。三、实验步骤和过程1.-搜索过程在

3、极小极大搜索方法中,由于要先生成指定深度以内的所有节点,其节点数将随着搜索深度的增加承指数增长。这极大地限制了极小极大搜索方法的使用。能否在搜索深度不变的情况下,利用已有的搜索信息减少生成的节点数呢?设某博弈问题如下图所示,应用极小极大方法进行搜索MINIMAX过程是把搜索树的生成和格局估值这两个过程分开来进行,即先生成全部搜索树,然后再进行端节点静态估值和倒推值计算,这显然会导致低效率。如图1中,其中一个MIN节点要全部生成A、B、C、D四个节点,然后还要逐个计算其静态估值,最后在求倒推值阶段,才赋给这个MIN节点的倒推值。其实,如果生成节点A后,马上进行静态估值,得知f(A)之后,就可以断

4、定再生成其余节点及进行静态计算是多余的,可以马上对MIN节点赋倒推值,而丝毫不会影响MAX的最好优先走步的选择。这是一种极端的情况,实际上把生成和倒推估值结合起来进行,再根据一定的条件判定,有可能尽早修剪掉一些无用的分枝,同样可获得类似的效果,这就是-过程的基本思想。2.利用-搜索过程的一字棋的实例图2一字棋第一阶段-剪枝方法 为了使生成和估值过程紧密结合,采用有界深度优先策略进行搜索,这样当生成达到规定深度的节点时,就立即计算其静态估值函数,而一旦某个非端节点有条件确定其倒推值时就立即计算赋值。从图2中标记的节点生成顺序号(也表示节点编号)看出,生成并计算完第6个节点后,第1个节点倒推值完全

5、确定,可立即赋给倒推值1。这时对初始节点来说,虽然其他子节点尚未生成,但由于s属极大值层,可以推断其倒推值不会小于1,我们称极大值层的这个下界值为,即可以确定s的1。这说明s实际的倒推值决不会比1更小,还取决于其他后继节点的倒推值,因此继续生成搜索树。当第8个节点生成出来并计算得静态估值为1后,就可以断定第7个节点的倒推值不可能大于1,我们称极小值层的这个上界值为,即可确定节点的1。有了极小值层的值,很容易发现若时,节点7的其他子节点不必再生成,这不影响高一层极大值的选取,因s的极大值不可能比这个值还小,再生成无疑是多余的,因此可以进行剪枝。这样一来,只要在搜索过程记住倒推值的上下界并进行比较

6、,就可以实现修剪操作,称这种操作为剪枝。类似的还有剪枝,统称为-剪枝技术。在实际修剪过程中,、还可以随时修正,但极大值层的倒推值下界永不下降,实际的倒推值取其后继节点最终确定的倒推值中最大的一个倒推值。而极小值层的倒推值上界永不上升,其倒推值则取后继节点最终确定的倒推值中最小的一个倒推值。2.1 在进行-剪枝时,应注意以下几个问题:(1)比较都是在极小节点和极大节点间进行的,极大节点和极大节点的比较,或者极小节点和极小节点间的比较是无意义的。(2)在比较时注意是与先辈层节点比较,不只是与父辈节点比较。当然,这里的先辈层节点,指的是那些已经有了值的节点。(3)当只有一个节点的固定以后,其值才能够

7、向其父节点传递。(4)-剪枝方法搜索得到的最佳走步与极小极大方法得到的结果是一致的,-剪枝并没有因为提高效率,而降低得到最佳走步的可能性。(5)在实际搜索时,并不是先生成指定深度的搜索图,再在搜索图上进行剪枝。如果这样,就失去了-剪枝方法的意义。在实际程序实现时,首先规定一个搜索深度,然后按照类似于深度优先搜索的方式,生成节点。在节点的生成过程中,如果在某一个节点处发生了剪枝,则该节点其余未生成的节点就不再生成了。2.2 -剪枝搜索过程(如图3)在搜索过程中,假定节点的生成次序是从上到下,从左到右进行的。图中带圈的数字,表示节点的计算次序,在叙述时,为了表达上的方便,该序号也同时表示节点。当一

8、个节点有两个以上的序号时,不同的序号,表示的是同一个节点在不同次序下计算的结果。过程如下: 图3 -搜索过程的博弈树 图3给出一个d4的博弈树的-搜索过程,其中带圆圈的数字表示求静态估值及倒推值过程的次序编号。该图详细表示出-剪枝过程的若干细节。初始节点的最终倒推值为1,该值等于某一个端节点的静态估值。最好优先走步是走向右分枝节点所代表的棋局,要注意棋局的发展并不一定要沿着通向静态值为1的端节点这条路径走下去,这要看对手的实际响应而定。2.3剪枝的效率问题若以最理想的情况进行搜索,即对MIN节点先扩展最低估值的节点(若从左向右顺序进行,则设节点估计值从左向右递增排序),MAX先扩展最高估值的节

9、点(设估计值从左向右递减排序),则当搜索树深度为D,分枝因数为B时,若不使用-剪枝技术,搜索树的端节点数;若使用-剪枝技术可以证明理想条件下生成的端节点数最少,有 (D为偶数)(D为奇数)比较后得出最佳-搜索技术所生成深度为D处的端节点数约等于不用-搜索技术所生成深度为D2处的端节点数。这就是说,在一般条件下使用-搜索技术,在同样的资源限制下,可以向前考虑更多的走步数,这样选取当前的最好优先走步,将带来更大的取胜优势。四、基于-剪枝的一字棋源代码#includeusing namespace std;int num=0; /记录棋盘上棋子的个数int p,q; int tmpQP33; /表示

10、棋盘数据的临时数组,其中的元素0表示该格为空,int cur33; /存储当前棋盘的状态const int depth=3; /搜索树的最大深度void Init() /初始化棋盘状态 for(int i=0;i3;i+)for(int j=0;j3;j+)curij=0;void PrintQP() /打印棋盘当前状态for(int i=0;i3;i+)for(int j=0;j3;j+)coutcurijt;coutendl;void UserInput()/用户通过此函数来输入落子的位置,比如:用户输入31,则表示用户在第3行第1列落子。int pos,x,y;L1: coutpos;x

11、=pos/10,y=pos%10;if(x0&x0&y4&curx-1y-1=0)curx-1y-1=-1;elsecoutInput Error!;goto L1;int CheckWin() /检查是否有一方赢棋(返回 0:没有任何一方赢;1:计算机赢;-1:人赢) /该方法没有判断平局for(int i=0;i3;i+)if(curi0=1&curi1=1&curi2=1)return 1;if(curi0=-1&curi1=-1&curi2=-1)return -1;for(i=0;i3;i+)if(cur0i=1&cur1i=1&cur2i=1)return 1;if(cur0i=-

12、1&cur1i=-1&cur2i=-1)return -1;if(cur00=1&cur11=1&cur22=1)|(cur20=1&cur11=1&cur02=1)return 1;if(cur00=-1&cur11=-1&cur22=-1)|(cur20=-1&cur11=-1&cur02=-1)return -1;return 0;int value()/评估当前棋盘状态的值(同时可以用p或q判断是否平局)p=0;q=0;for(int i=0;i3;i+) /计算机一方 /将棋盘中的空格填满自己的棋子,既将棋盘数组中的0变为1for(int j=0;j3;j+)if(curij=0)t

13、mpQPij=1;elsetmpQPij=curij; for(i=0;i3;i+) /计算共有多少连成3个1的行p+=(tmpQPi0+tmpQPi1+tmpQPi2)/3;for(i=0;i3;i+) /计算共有多少连成3个1的列p+=(tmpQP0i+tmpQP1i+tmpQP2i)/3;p+=(tmpQP00+tmpQP11+tmpQP22)/3;/计算共有多少连成3个1的对角线p+=(tmpQP20+tmpQP11+tmpQP02)/3; for(i=0;i3;i+) /人一方 /将棋盘中的空格填满自己的棋子,既将棋盘数组中的0变为-1for(int j=0;j3;j+)if(curij=0)tmpQP

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 生活休闲 > 科普知识

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号