围棋AI之路(二)棋盘的实现

本文探讨了围棋AI中的棋盘实现,使用模板类定义不同尺寸的棋盘,并介绍了颜色遍历优化和循环展开技术。同时,讨论了组合类设计,包括私有与公有访问权限的选择,以及如何优雅地处理成员间的相互调用。
摘要由CSDN通过智能技术生成
代码先公布:http://download.csdn.net/source/891878

到现在为止,我只实现了一个棋盘,确切的说是在棋盘上随机走棋的速度测试程序,我借鉴了lib-ego,在上面做了一些改进,现在这个棋盘可以使用围棋规则或者五子棋规则。我的目标是让我的AI程序用同样的算法来对待围棋、五子棋甚至小时候玩过的黑白棋,它不需要任何棋类知识,你只要告诉它下棋的规则。我们的脑细胞可曾了解究竟什么是围棋?它们只是机械的执行自己的职能,而亿万个细胞堆叠在一起就使人类会下棋了。

上面说的三种棋的棋盘有一些共同的特点:棋盘是由n行n列的平行线段交叉组成的格子,棋子分黑白两种颜色,棋手分为两方,分执一种颜色的棋子。双方轮流下子,每次下一个子,棋子要下在空的交叉点上(黑白棋似乎是下在格子里,但是应该没有本质区别)。

根据这些特点我们开始设计棋盘的结构。

一、比特棋盘

很想在围棋中使用比特棋盘,就像国际象棋中那样,用一个64bit的数就描述了棋盘上的一种棋子。围棋上尽管也可以做到,例如用一个361bit的数来描述棋盘上的黑棋,另一个361bit数描述白棋,但是没见过谁这么做。

一般还是用传统的数组来描述棋盘,数组的每个元素有三个状态:黑(black)、白(white)、空(empty)。

为何计算机不是三进制的?我以前曾经这么想过,如果计算机是三进制的,会不会能更好的描述围棋?

后来我发现,其实棋盘上的点不只三个状态,还漏掉了一个off_board,也就是棋盘外的点。因此棋盘其实是4进制的,和2进制的计算机还是契合的不错的。

如何理解off_board也是一种状态?我们可以观察一下棋盘的边界,边界再往外就是off_board了,对围棋来说,通常的一颗子有4口气,但是到边界上就变成三口气或者两口气了,就仿佛边界外有敌人的子一样。对于五子棋,如果对方冲四冲到边界上,就不用挡了,就好像棋盘外有自己的棋子给它挡住了一样。

我按这种物理意义来为这些状态指派2进制数:

empty 00
black 01
white 10
off_board 11

这里empty就是没有棋子,black和white分别有一个棋子,而off_board则是同时有两个棋子,哪方的棋子靠近它,它就表现为另一方。

这样做的好处是,我可以用一个8bit的数来描述一个棋子的邻点,8bit总共256种情况,非常适合查表,通过查表,我就能得知任何情况下交叉点的“气”了。

关于计算交叉点的“气”,lib-ego中采用的另一种方法,它仅仅只增量计算交叉点周围黑、白、空三种情况的数量(off_board就分摊到黑白两种情况上了),而不管具体分布情况。目前我还没有发现我的方法表现出来的优势,但是我坚信我的方法比lib-ego中的好,因为它合乎道。

看起来,可以用一个8bit的数来存4个位置的状态,那么整个棋盘总共需要56个64bit数,比国际象棋没多太多,然而最终我没有贯彻比特棋盘的思想,因为我觉得那样不自然,我仍然选用传统的数组方式。

二、代码优化

许多人都指出优化应该晚做。但是对一份已经优化过的代码,如果不了解其优化手段,很难明白一些代码的意义。

1 使用编译期常量来代替变量。
例如棋盘的尺寸这个量,棋子的坐标计算依赖于它,为一些结构分配多大空间也与这个量相关。为了避免运行期再去计算这些东西,我们可以用宏或者const int来定义它:
  1. const uint board_size = 9;
但是我们希望
  • 2
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值