五子棋AI算法的改进方法讲解
又是本人一份人工智能作业……首先道歉,从Word 贴到 Livewrter,好多格式没了,也没 做代码高亮……大家凑活着看……想做个好的人机对弈的五子棋,可以说需要考虑的问题还 是很多的,我们将制作拥有强大AI 五子棋的过程分为十四步,让我来步步介绍。 第一步,了解禁手规则第一步,了解禁手规则 做一个五子棋的程序, 自然对五子棋需要有足够的了解, 现在默认大家现在和我研究五子棋 之前了解是一样多的。以这个为基础,介绍多数人不大熟悉的方面。 五子棋的规则实际上有 两种:有禁手和无禁手。由于无禁手的规则比较简单,因此被更多人所接受。其实,对于专 业下五子棋的人来说,有禁手才是规则。所以,这里先对“有禁手”进行一下简单介绍: 五子棋中“先手必胜”已经得到了论证,类似“花月定式”和“浦月定式”,很多先手必胜下法虽 然需要大量的记忆, 但高手确能做到必胜。 所以五子棋的规则进行了优化, 得到了 “有禁手” 五子棋。 五子棋中, 黑棋必然先行。 因此“有禁手”五子棋竞技中对黑棋有以下“禁手”限制:“三 三禁”:黑棋下子位置同时形成两个以上的三;“四四禁”:黑棋下子位置同时形成两个以上的 四;“长连禁”:六子以上的黑棋连成一线。黑棋如下出“禁手“则马上输掉棋局。不过如果“连 五”与“禁手”同时出现这时“禁手”是无效的。所以对于黑棋只有冲四活三(后面会有解释) 是无解局面。反观白棋则多了一种获胜方式,那就是逼迫黑棋必定要下在禁点。 为了迎合所有玩家,五子棋自然需要做出两个版本,或者是可以进行禁手上的控制。 第二步,实现游戏界面第二步,实现游戏界面 这里,我制作了一个简单的界面,但是,对于人机对弈来说,绝对够用。和很多网上的精美 界面相比,我的界面也许略显粗糙,但,开发速度较高,仅用了不到半天时间。下面我们简 单看下界面的做法。 界面我采用了 WPF,表现层和逻辑层完全分开,前台基本可以通过拖拽完成布局,这里就 不做过多介绍。根据界面截图简单介绍 1 处实际上市两个渐变 Label 的拼接,2、3 是两个 label,4、5 实际上是两个 Button, 但是没有做事件响应。通过按钮6、7、8、9 的控制,修改 label 和 Button 的 Content 属性。也许有人会奇怪,为什么Button 会丝毫看出不出有 Button 的影子,这里战友 whrxiao 写过一个 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 的基础,接下来就是一些博弈的方法了。 第五步:得到位置估分第五步:得到位置估分 AIAI 单纯应用棋谱以及对五子棋当前局势的分析, 对每步进行估分,程序中做如下工作:将每个 位置进行分析,假设 AI 落子在该位置,用以上打分规则为AI 打分,并将得到的分数加一。 然后,假设玩家落子在该点,为玩家打分,然后将所有的分值汇总。取最高分作为这个位置 的估分,接下来就是取分数最高的位置下棋了。 “位置估分”,下棋的时候,既可以考虑到自 己攻击对手,又能考虑到对对手的防御,可以说,很多时候可以顶上考虑两步的AI。作实 验,从网上下载了一个用博弈做的AI,和“位置估分”对下,结果是一胜一负。谁先子,谁 赢得胜利。而且一步估分毫无疑问是最快的,即使遍历所有位置,也能很快的做出决策。 第六步:应用博弈树,提高第六步:应用博弈树,提高 AIAI 智能智能 做五子棋的博弈,自然会用到博弈树,这里我说下自己的思路。在对弈中,根据下一步由谁 来走,AI 对任何一个局面根据前面估分方法给出一个分数,我们把这个估分方法汇总成一个 评估函数,并返回分值。据此来选择下一步的走法。由于人和AI 是轮流落子,可以将人的 估分也算入,并将前面加负号。那么,估值越大表明对AI 越有利,估分越小则表明对AI 越不利。那么每次AI 选择都是从它可能的走法树的某层节点,返回评估值中最大点。而用 户总是从走法树的某层节点中选择最小点, 从而形成一棵极大极小搜索树, 然后根据深度优 先搜索, 可以最后得到固定搜索深度下的一个最好的走法。 我做了下试验, 单纯应用博弈树, 可以在 100ms 之内让 AI 考虑完整的两步,由于组合爆炸,当需要考虑三步的时候,就需 要 6s 左右,4 步就需要 1 分钟。拿两步来和一步估分作比较,虽然比较慢,但是确实有了 一定智