如何写一个象棋 AI (一)

本文代码:github.com/ParadeTo/ch…node

Demo 地址:www.paradeto.com/chinese-che…git

咱们都知道,把大象关进冰箱须要三步。同理,写一个象棋 AI 程序也只须要三步:github

  1. 遍历出全部可能的走法
  2. 选择出最好的走法

第三步其实只是凑数而已,能够去掉,这样写一个 AI 程序就更简单了,只须要两步。算法

其中,第一步对于稍微有点象棋和编程知识的人来讲并非很难,除了马和炮的走法须要写一些额外的规则来判断之外,其余的棋子都比较相似,这一部分不在本文的讨论范围以内。编程

第二步才是本文须要讨论的重点,首先咱们要解决的第一个问题是,给定一个棋局,如何判断该棋局的好坏呢?bash

局势评估

关于象棋局势的评估已有很多学者作过研究,有静态单子型、将来局势型、象棋知识型、局面附加信息等。本文采起的是静态单子型。优化

所谓静态单子型评估,是指对棋盘上的每个棋子考虑其种类和位置,依种类的重要性与位置的优劣决定它的评估值,而后将棋盘上全部己方棋子的评估值直接累加获得己方战力值,将对手全部棋子的评估值累加获得对手战力值,已方战力值减去对手战力值获得最终的局势评估值。ui

最大最小值算法

有了局势评估方法后,每次遍历出全部的可能走法,而后从中选取局势分数最高的走法就是一个最简单的象棋 AI 了。不过这个 AI 会有点蠢,有点短视。想一想小时候跟院子里的老大爷下棋时是怎么被玩弄的吧,老大爷老是故意让一个车给你吃,而正当你开心得得意忘形的时候,一声 “将军” 瞬间让你跌回了深渊,死棋,游戏结束。每当这个时候,心中总会暗忖,这个老头子可真阴险。后来才知道,对付这种阴险的战术须要咱们下棋时能抵抗住诱惑,看得更加长远一些,不能只顾当前这一步,要考虑到后面两步、三步……的状况。spa

既然这样,那程序实现起来也简单,无非就是递归的遍历几层,达到叶子节点后计算当前局势得分,而后选择分数最高的不就能够了。就像下图这样:code

我先遍历出全部可能的走法(图中黑色方块),而后基于该层的走法继续遍历(图中最后一排的白色方块),计算局势分数,选择最高分数的走法,即选择左边黑色方块的走法。可是,你忘记了一点,你走完后,接下来是轮到你对手走了,你若是想获得 100 的分数,就须要你的对手配合你选择分数 100 的走法。很明显你的对手不会那么傻,此时,只要他跟你同样聪明,他应该会选择走分数为 1 的那一步。而若是你选择右边黑色方块的走法,你的对手会选择分数为 33 的走法,你反而会获得一个高一点的分数。

让咱们用一个别的例子再来模拟一下上面的情景,以便更好的理解。假设你朋友给你两个袋子,第一个袋子里面装了一颗螺丝和一台 Mac Pro,第二个袋子里面装了一台小米9和一台华为p30。而后跟你说,选择一个袋子,而后我从里面拿一个礼物送给你。你会怎么选?你确定选第二个袋子是吧。固然,这里重要的一点是你的朋友智商必定要正常,若是是个傻子的话,保不许你选了第一个袋子,他会送台 Mac 给你。

人能够作出这样的决策这很正常,可是如何教会计算机也这样思考呢?这就须要用到最大最小值算法了。最大最小算法把搜索树分红最大值层和最小值层,AI 处于最大值层,对手处于最小值层,最大值层老是从下一层选取最大的值做为结果,最小值层老是从下一层选择最小值做为结果。以下图所示:

思路清楚了,代码实现起来就很简单了,如下是来自 wiki 的一段伪代码:

function minimax(node, depth, maximizingPlayer) is
    if depth = 0 or node is a terminal node then
        return the heuristic value of node
    if maximizingPlayer then
        value := −∞
        for each child of node do
            value := max(value, minimax(child, depth − 1, FALSE))
        return value
    else (* minimizing player *)
        value := +∞
        for each child of node do
            value := min(value, minimax(child, depth − 1, TRUE))
        return value
复制代码

总结

本文阐述了实现一个象棋 AI 的基本步骤,引出了最大最小值算法并经过例子加以分析。不过该算法比较耗时,假设每次遍历平均产生 30 种走法,则深度为 5 的 AI 的一共须要进行 24300000 次的局势分数计算。事实上该算法经过必定的规则能够进行优化,这个就留在下一篇文中再进行论述吧。

参考

  1. 中国象棋计算机博弈局面评估技术研究
  2. Minimax
  3. IntelligentChineseChessSystem
  4. gobang
相关文章
相关标签/搜索