当前位置:文档之家› 五子棋AI算法的改进方法讲解--实用.doc

五子棋AI算法的改进方法讲解--实用.doc

又是本人一份人工智能作⋯⋯首先道歉,从Word到Livewrter,好多格式没了,也没做代高亮⋯⋯大家凑活着看⋯⋯想做个好的人机弈的五子棋,可以需要考的是很多的,我将制作有大AI 五子棋的程分十四步,我来步步介。

第一步,了解禁手做一个五子棋的程序,自然五子棋需要有足的了解,在默大家在和我研究五子棋之前了解是一多的。

以个基,介多数人不大熟悉的方面。

五子棋的上有两种:有禁手和无禁手。

由于无禁手的比,因此被更多人所接受。

其,于下五子棋的人来,有禁手才是。

所以,里先“有禁手” 行一下介:五子棋中“先手必”已得到了,似“花月定式”和“浦月定式”,很多先手必下法然需要大量的,但高手确能做到必。

所以五子棋的行了化,得到了“有禁手”五子棋。

五子棋中,黑棋必然先行。

因此“有禁手”五子棋技中黑棋有以下“禁手”限制:“三三禁”:黑棋下子位置同形成两个以上的三;“四四禁”:黑棋下子位置同形成两个以上的四;“ 禁”:六子以上的黑棋成一。

黑棋如下出“禁手“ 上掉棋局。

不如果“ 五”与“禁手”同出“禁手”是无效的。

所以于黑棋只有冲四活三(后面会有解)是无解局面。

反白棋多了一种方式,那就是逼迫黑棋必定要下在禁点。

了迎合所有玩家,五子棋自然需要做出两个版本,或者是可以行禁手上的控制。

第二步,游界面里,我制作了一个的界面,但是,于人机弈来,用。

和很多网上的精美界面相比,我的界面也略粗糙,但,开速度高,用了不到半天。

下面我看下界面的做法。

界面我采用了 WPF ,表和完全分开,前台基本可以通拖拽完成布局,里就不做多介。

根据界面截介1 处实际上市两个渐变Label 但是没有做事件响应。

通过按钮属性。

也许有人会奇怪,为什么的拼接,2 、3 是两个 label ,4 、 56 、7 、8 、9的控制,修改labelButton 会丝毫看出不出有Button实际上是两个Button,和 Button的Content的影子,这里战友whrxiao 写过一个Style 如下<Style x:Key="ButtonStyle1" TargetType="{x:Type Button}"><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="{x:Type Button}"><Grid><ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" RecognizesAccessKey="True"/></Grid></ControlTemplate></Setter.Value></Setter></Style>这里我们把这个Style称为Style1。

界面逻辑上,将是否开始、是否禁手和是否电脑先行作为两个全局变量的布尔型值,通过设置和判断 bool 型值进行逻辑上的控制。

中间的棋盘是个canvas ,一个 15*15 的 Grid 放满 Button 并将每个 Button 应用 Style1 开始时候透明度设为 0 ,也就是根本看不到,在下棋的时候改变 Button 的背景和透明度,实现落子的效果,因为Grid的位置关系,所以可看起来好像是下在横竖的交线处。

第三步,进行输赢判断:因为规则不同,“无禁手”和“有禁手”的输赢判断自然不同。

先看无禁手:这个比较简单,遍历每个位置,然后从这个位置开始,分别判断它的四个方向:即横、竖、左上到右下、左下到右上。

每个方向从中间点开始,往两边数连子数,然后将两个方向的连字数加和再加一(中间的棋子)。

如果得到大于等于 5 ,那么就说明下子方赢棋。

对于有禁手的五子棋,输赢判断还需要判断禁手,禁手的判定较为复杂。

将待判断点放入黑棋子。

然后搜索待判断点周边棋盘;还原棋盘;利用搜索结果依次对各方向进行分析,判断黑棋放入后所产生的棋型是否形成长连或形成某种四连或三连的的棋型。

若形成长连,判定为禁手,返回长连禁手标识。

若形成某种四连或三连的棋型,该棋型统计数加 1 ,再对下一个方向进行判断,直到各个方向分析结束。

若四连棋型或三连棋型的统计数大于1,则返回为禁手。

其余情况返回非禁手。

第四步:构造棋型估分“有禁手”规则比较复杂,涉及到比较多下棋方面的技巧,而且对算法的思路没有丝毫影响,所以下面我们主要考虑无禁手规则下的AI 设计。

若设计好无禁手AI ,只需要让AI 执黑时坚决不下到禁手点,就可以很快构造有禁手的 AI 。

虽然这种方式没有利用有禁手规则下的技巧,但这些技巧只需要修改下面所讲到的估分函数即可。

我们可以将五子棋的连珠可以分为以下几种:成 5 :即构成五子连珠活4 :即构成两边均不被拦截的四子连珠。

死 4 :一边被拦截的四子连珠活3 :两边均不被拦截的三字连珠死3 :一边被拦截的三字连珠活 2 :两边均不被拦截的二子连珠死2 :一边被拦截的二子连珠单子:四周无相连棋子根据五子棋的技巧,可以将五子棋的棋型用连珠进行分类,分类过后我们按照威力给每种棋型打分。

因为五子棋一次只落一子,因此很容易理解,双活三和三活三的威力是一样的,类似情况不多做解释。

程序中,我以100 分为满分,对棋型进行了以下打分:成5, 100 分活4 、双死 4 、死 4 活 3 , 90 分双活 3 , 80 分死3 活 3 , 70 分死4 , 60 分活3 , 50 分双活 2 , 40 分死 3 , 30 分活2 , 20 分死 2 , 10 分单子 0 分有了估分方法,就有了五子棋AI 的基础,接下来就是一些博弈的方法了。

第五步:得到位置估分AI单纯应用棋谱以及对五子棋当前局势的分析,对每步进行估分,程序中做如下工作:将每个位置进行分析,假设AI 落子在该位置,用以上打分规则为AI 打分 ,并将得到的分数加一。

然后,假设玩家落子在该点,为玩家打分,然后将所有的分值汇总。

取最高分作为这个位置的估分,接下来就是取分数最高的位置下棋了。

“位置估分”,下棋的时候,既可以考虑到自己攻击对手,又能考虑到对对手的防御,可以说,很多时候可以顶上考虑两步的AI 。

作实验,从网上下载了一个用博弈做的AI ,和“位置估分”对下,结果是一胜一负。

谁先子,谁赢得胜利。

而且一步估分毫无疑问是最快的,即使遍历所有位置,也能很快的做出决策。

第六步:应用博弈树,提高AI 智能做五子棋的博弈,自然会用到博弈树,这里我说下自己的思路。

在对弈中, 根据下一步由谁来走 ,AI 对任何一个局面根据前面估分方法给出一个分数, 我们把这个估分方法汇总成一个评估函数,并返回分值。

据此来选择下一步的走法。

由于人和AI 是轮流落子,可以将人的估分也算入,并将前面加负号。

那么,估值越大表明对AI 越有利,估分越小则表明对AI 越不利。

那么每次AI 选择都是从它可能的走法树的某层节点,返回评估值中最大点。

而用户总是从走法树的某层节点中选择最小点,从而形成一棵极大极小搜索树,然后根据深度优先搜索,可以最后得到固定搜索深度下的一个最好的走法。

我做了下试验,单纯应用博弈树,可以在 100ms之内让AI考虑完整的两步,由于组合爆炸,当需要考虑三步的时候,就需要6s 左右, 4 步就需要 1 分钟。

拿两步来和一步估分作比较,虽然比较慢,但是确实有了一定智能。

第七步:考虑层数,提高AI 智能上面的设计对于返回值是统一处理的, 但是,层数是个很重要的信息. 因为下棋时如果能 2 步获胜 , 不应选择 4 步获胜。

对于输的棋型层数就更重要,AI 必须尽可能拖延输的时间,就有更大的可能让AI 化险为夷。

这样,可以通过设置一个dep 值。

深度约浅,dep 越大,用dep 和得到的得分相乘,得到搜索节点的得分,再进行以上算法,进一步提高AI 的智能。

第八步:应用α- β剪枝,提高AI速度在搜索博弈树的过程中,实际上搜索有很多点是多余的,例如下图图中,方形框节点是该AI 走 , 圆形框节点是该人走 .比如 C 节点 , 它需要从 E 和 F 当中选取最大的值。

目前已经得出 E 为 2, 当搜索 F 节点时 , 因为 F 是人走的节点,那么 F 需要从 K L M 中选取最小的,因为K 已经是 1 ,也就是说 F<=1 ,那么 L, M 就不需要搜索,因此就发生了α剪枝。

然后看 A 节点,该人走了,需要从 C 和 D 中选取最小值,因为 C 节点是 2 ,而 G 是 7 ,那么 D 至少是 7 。

因此, D 的其他节点不必再考虑,就发生如上图所示的β剪枝。

总结上面规律,我们可以得到剪枝方法如下:当前为 AI 下棋节点:α剪枝:如果当前节点的值不比父节点的前兄弟节点的大值大, 则舍弃此节点。

β剪枝:如果当前节点子节点的值不比当前节点的前兄弟节点中的最小值小, 则舍弃该子节点和该子节点的所有后兄弟节点。

当前为用户下棋节点:α剪枝:如果当前节点的某子节点的值不比当前节点的前兄弟节点中的最大值大, 则舍弃该子节点和该子节点的所有后兄弟节点。

β剪枝:如果当前节点的子节点的值不比当前的父节点的前兄弟节点中的最小值小则舍弃此节点。

经过α- β剪枝,可以极大的减少搜索的数量,很多时候,能把几十亿的搜索数量,缩小到几亿,那么,就可以把搜索深度增 1 。

第九步:应用下棋范围,提高AI 速度当前节点的子节点的数量和排列顺序对于搜索的速度起着至关重要的影响。

根据五子棋的特点, 可, 以产生一个棋面搜索范围。

记录当前棋面所有棋子的最左最右最上最下点构成的矩形我们认为下一步棋的位置不会脱离这个框 3 步以上。

这样在棋子较少的时候,搜索节点的数量大大减少。

可以将AI 的速度提高一倍左右。

第十步:利用棋型得分,提高AI 速度,因为每种下法都对应一种得分,所以,可以每次只考虑当前得分前十的节点进行下一步搜索大大减少了搜索范围,可以进一步增加搜索的深度。

第十一步:利用置换表,提高AI 速度我们一般用递归的方法实现博弈树,但是,递归的效率是低的,而且很明显,有很多重复搜索的节点,所以,我们可以用一个表,记录下所有搜索过节点的情况,然后只要遇到搜索到的节点,就可以直接得到结果。

相关主题