井字棋策略
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
一、问题描述
井字棋的棋盘是一个九宫格(即3×3的方格),因此通常可以在纸上画一个井字来做棋盘用,井字棋因此得名。下棋时双方交替向棋盘上布子,每个棋子要落在尚无棋子的方格内。棋子落下后不能移动,无吃子一说。当其中任意一方有三个棋子连成一线(横向、纵向或斜向均可)时,即为“胜”,另一方为“负”。如果棋盘上9个棋格都摆满了棋子,双方都没有连成一线的三子,即为“和棋”。
二、算法分析
在对弈问题中,计算机操作的数据对象是每走一步棋后形成的棋盘状态(格局),对每一个格局来说,它的下一步棋都有若干不同的走法,这样一层一层就形成了一个状态空间树。
处于某一格局时,计算机又是如何选择走下一步棋呢? 当然是选择对自己有利的格局,而电脑是如何识别有利的格局?一般是使用一个估价函数,对每个格局进行“估价”,假设估价函数值越大,表示对电脑走棋越有利,那么,电脑在走下一步棋时,只要搜索出估价函数值最大的格局即可。实际上,很难找到一个准确的函数来完全反映复杂的格局,但希望它尽可能的接近。
在井字棋中,如果计算机赢value = + 1 ,对手赢value = - 1 ,平局value = 0 ,而这些格局可作为博奕树的终端结点;对于非终端结点,电脑走棋会选估价函数值高的格局,当然对手走棋会选函数值低的格局,这样非终端结点的函数值就由其下层结点的这种最大最小交
替递归调用得到,称为最小最大搜索算法。在图1 中,格局B、C 因对手走一步棋即赢,函数值为- 1 ,格局E 因电脑走一步棋即赢,函数值为+ 1 ,格局G平局,函数值为0 ,格局F 为电脑下棋,函数值F = Max( G) = 0 ,格局D 为对手下棋,D =Min(E ,F) = 0 ,格局A 为电脑下棋,A =Max(B ,C) = 0。下面给出这种最小最大搜索算法中,电脑和对手的走棋程序
int comp ( Int &move)
{
int i ,response ,p ;
int value = - 2 ; //设临时最大值初始为- ∞
if (full () ) return(0) ;//棋盘满为平局
if (win-comp () ) return(1) ;//走一步棋,计算机赢
for (i = 0 ;i < 9 ;i + + )//测试棋盘上所有方格
if (chess[ i ] = = 0) //方格未落子
{chess[ i ] = 1 ;//计算机下子为1
response = human() ;
chess[ i ] = 0 ;//恢复棋盘
if (response > value)
{ value = response ;
move = i ; }
}
return value ;
}
int human(int &move)
{
int i ,response ,p ;
int value = 2 ; //设临时最小值初始为+ ∞+
if (full () ) return (0) ;
if (win- human() ) return ( - 1) ; //走一步棋,对手赢for (i = 0 ;i < 9 ;i + + )
if (chess[ i ] = = 0)
{chess[ i ] = 2 ; //对手下子为2
response = comp (p) ;
chess[ i ] [ j ] = 0 ; //恢复棋盘
if (response < value)
{ value = response ;
move = I ;}
}
return value ;
}
对于一些更加复杂的游戏,如国际象棋、跳棋、五子棋等,要想搜索到终端结点是很困难的,甚至是不可能的,我们可以往下搜索几层,把最低一层看成终端结点,其估价函数值根据对格局的分析近似得出。
2. 设计方案
2.1 设计步骤
本程序最主要的任务是完成图形界面的井字棋的人机对弈模块的设计。在人机对弈过程中,计算机方所采用的算法,也就是博弈树的搜索技术是最重要的。所以,设计时,作者按照以下步骤进行:
(1) 选定博弈算法;
(2) 建立一个简单的应用程序(如字符界面程序)来测试算法;
(3) 选定图形界面中要实现的其他功能(如双人对弈、悔棋、难易级别选定、联机对战等);
(4) 实现图形界面的井字棋程序。
所采用的核心算法为极大极小值算法。极大极小值算法的核心是将搜索树的层分为MAX层和MIN层,MAX层和MIN层交替相邻(即,一个节点如果在MAX层,则其子女节点在MIN层;如果在MIN层,则其子女节点在MAX层),在MAX层的节点的评估函数值取其子女节点中的最大者,在MIN层的节点的评估函数值取其子女节点中的最小者。
此外,需要定义一个评估函数来计算叶节点的评估函数值,要注意将某方获胜的状态节点的评估函数值设为计算机能表示的最大数(无穷大)或最小数(无穷小)以表明在该状态下有一方获胜。
最后,还要“在有限的搜索深度范围内进行求解”,如果搜索深度太大,则在状态数较多的情况下会使时间耗费或空间耗费达到无法忍受的程度。
可以通过增加生成树的层数,即增加TREE_DEPTH的值来提高计算机的智商。这相当于增加了计算机向前预测的步数。对井字棋来说,因为井字棋有9个格,所以TREE_DEPTH的最大值可以设为9,但是实际上,经过试验,当TREE_DEPTH=3时,计算机对井字棋的落子的处理就能达到比较好的效果。。