前面几篇文章详细介绍了棋盘类的封装, 棋子类的封装以及各种类型的棋子的走棋算法的实现. 有了前面的铺垫, 就能迈出人工智能的第一步了. 本系列博客还是重点介绍实现方法, 很多的代码都不再过多解释了.
下面是我整理好的 C/C++ 学习资料, 加小编 C/C++ 学习群 (825414254) 获取一套系统性的学习 C/C++ 教程哦!
image
人机对战类:
image
由以上代码可以看出, 人机对战类继承自棋盘类, 重载了棋盘类中的 click 函数. 其中, Step 是一个 QVector 容器, 其内部情况是这样的:
image
由以上代码可以看出 Step 类是用来存放走棋信息的.
人机对战类中重载的 click 函数源代码:
image
由以上代码可以看出, 人类方走红棋, 电脑方走黑棋. 当轮到红方走棋的时候, 与人人对战的时候没有区别, 于是调用父类中的 click 函数; 当轮到黑方走棋的时候, 就获取对电脑最有利的走棋路径, 让电脑走棋.
人工智能的实现分 3 步走
1. 获取所有走得通的路径
上 getAllPossibleMove 函数的源代码:
image
算法解析: 遍历所有黑方的棋子, 遍历到某一棋子时全方位无死角地遍历棋盘上的所有位置, 把每个位置的信息都输入 canMove 函数, 将 canMove 函数返回 true 的 "步" 存放到容器 steps 中.
2. 从所有能走的路径中找到对电脑最有利的路径
上 getBestMove 函数的源代码:
image
算法解析: 这便是模拟人的思维的过程, 从小跟爷爷下棋的时候爷爷就对我说, 要走一步看三步, 然而这里先实现走一步看一步. 路边两个老爷爷在下棋, 老爷爷虽然不会摆弄棋盘上的棋子, 然而他的脑子里是在推演的, 他也会权衡一下选择对自己最有利的路径走棋. fakeMove 和 unfakeMove 便是推演的过程, 假想自己走一步, 评估完局面分再走回来. 找到走完后局面分最高的路径作为返回值返回.
关于 fakeMove 函数和 unfakeMove 函数:
image
image
其中 killStone 函数是用来杀死棋子的, relieveStone 函数是用来复活棋子的.
获取最优走棋路径这一步中有个很重要的步骤就是评估局面分, 上 calcScore 函数的源代码:
image
算法分析: 先给所有棋子分配权重, 根据棋子的重要程度来分配. 将是最重要的棋子, 因此将的权重最高, 置为 1500; 车其次, 置为 100, 马和炮再其次, 置为 50; 兵再再其次, 置为 20; 士和相最不重要, 置为 10. 遍历红方所有的棋子, 将红方活着的棋子的权重累加出一个总分; 遍历黑方所有的棋子, 将黑方活着的棋子的权重累加出一个总分. 因为黑方是电脑, 所以返回的局面分应该以黑方的角度计算, 返回黑棋总分 - 红棋总分.
3. 电脑走棋
这一部分在上面的 click 函数中有体现, 请自行往上翻.
来源: http://www.jianshu.com/p/65316d69b816