五子棋AI算法-Zobrist

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了五子棋AI算法-Zobrist相关的知识,希望对你有一定的参考价值。

  这个博客不是把五子棋算法研究透彻之后再写的,而是一边研究算法一边写代码,同时一边写博客,所以有些博文的顺序不太对,比如 Zobrist 其实应该放在算杀之前就讲的。不过这并没有大的影响,总体上的顺序是OK的。

  另外,这一系列博客讲的五子棋代码其实是一个开源的项目,源码地址:https://github.com/lihongxun945/gobang

  由于是边写代码边写博客,所以博客中的代码不是最新的,甚至是有bug的,所以源码请尽量参考上述开源项目中的代码。比如之前讲极大极小值搜索改为负极大值的时候,对玩家的评分就出现了一个重要bug,在后序的提交中修正了这个bug。

Zobrist

  Zobrist 是一个快速Hash算法,非常适合用在各种棋类游戏中(事实上也是在各种棋类游戏中有大量应用)。

  我们前面讲了负极大值搜索和算杀,其实很多时候会有重复的搜索,比如这种:

[7,7],[8,7],[7,6],[7,9]

  其实它和下面这种的走法只是顺序不同 ,最终走出来的局面是一样的:

[7,6],[7,9],[7,7],[8,7]

  那么如果我们搜索中碰到了上面两种情况,我们会对两种情况都进行一次打分,而其实有了第一次的打分,完全可以缓存起来,第二次就不用打分直接使用缓存数据了。除了这种情况,其实以前的搜索结果也可以存下来,可以用在启发式搜索中。

  那么现在的问题就是,我们应该怎么表示一种局面呢?显然需要通过一种哈希算法,而且这个算法不能太慢,不然可能反而会降低搜索速度。而 Zobrist 就是一种满足我们需求的快速数组哈希算法。关于Zobrist算法请参考 https://en.wikipedia.org/wiki/Ben_Zobrist

  Zobrist 效率非常高,每下一步棋,只需要进行一次 异或 操作,相对于对每一步棋的打分来说,这一次异或操作带来的性能消耗可以忽略不计。Zobrist具体实现如下:

  • 初始化一个两个 Zobrist[M][M] 的二维数组,其中M是五子棋的棋盘宽度。当然也可以是Zobrist[M*M] 的一维数组。设置两个是为了一个表示黑棋,一个表示白旗。
  • 上述数组的每一个都填上一个随机数,至少保证是32位的长度(即32bit),最好是64位。初始键值也设置一个随机数。
  • 每下一步棋,则用当前键值异或Zobrist数组里对应位置的随机数,得到的结果即为新的键值。如果是删除棋子(悔棋),则再异或一次即可。

对应的JS代码如下:

 1 var Zobrist = function(size) {
 2   this.size = size || 15;
 3 }
 4 
 5 Zobrist.prototype.init = function() {
 6   this.com = [];
 7   this.hum = [];
 8   for(var i=0;i<this.size*this.size;i++) {
 9     this.com.push(this._rand());
10     this.hum.push(this._rand());
11   }
12 
13   this.code = this._rand();
14 }
15 
16 Zobrist.prototype._rand = function() {
17   return Math.floor(Math.random() * 1000000000);  //再多一位就溢出了。。
18 }
19 
20 Zobrist.prototype.go = function(x, y, role) {
21   var index = this.size * x + y;
22   this.code ^= (role == R.com ? this.com[index] : this.hum[index]);
23   return this.code;
24 }

  源码在 zobrist.js 文件里。

  注意每次走棋都要进行一次zobrist操作。千万不要自行设计哈希函数,除非你能保证你的哈希函数比一次64位整数的异或操作更简单,并且同时证明冲突的概率很低。Zobrist数组中的随机数的 质量 很重要,不过我用JS内置的 Math.random() 生成的随机数暂时没有发现问题,如果这个随机度不够高,可以考虑换用一些更好的随机函数。

  有了这个快速hash算法,我们就可以通过一个64位的整数来表示一个棋局。至于该存哪些信息,该怎么使用,下一篇再讲。

以上是关于五子棋AI算法-Zobrist的主要内容,如果未能解决你的问题,请参考以下文章

AI五子棋第二篇-运用极大极小值算法书写AI三子棋,可拓展到五子棋(建议收藏)

AI五子棋-第三周-需求改进&系统设计

五子棋AI算法

人机ai五子棋 ——五子棋AI算法之Java实现

五子棋AI算法第二篇-极大极小值搜索算法

C# winform GDI+ 五子棋 :根据博弈算法写的人机AI(抄的别人的)