0%

围棋之气的计算

本文是围棋程序中最基本的气的计算,一块棋的计算一共分为三步计算,第一步计算棋盘中所有空闲的交叉点;第二步对某块棋子的相邻的交叉点进行标记;第三步将第一步和第二步的结果相交得到交集;实现代码使用swift语言.以下是具体步骤:

1. 计算棋盘中所有空闲的交叉点

所有白色棋子和黑色棋子的值的并集,使用一个全1的矩阵相减。
代码如下所示:

1
2
3
4
5
6
7
8
9
10
var emptiesNodes = Array2D(columns: 13+1, rows: 13+1, initialValue: 0)
// 计算空闲的交叉点
func do_cal_emptyies() {
for x in 1...13 {
for y in 1...13 {
emptiesNodes[x,y] = blackNodes[x,y] | whiteNodes[x,y]
emptiesNodes[x,y] = 1 - emptiesNodes[x,y]
}
}// end for
}

结果如下图所示:

2. 对某块棋子的相邻的交叉点进行标记

上一篇文章说明了围棋的棋子根据连接情况进行分块
以下面这张图的2号块棋子为例进行说明:

根据序号等于2号的交叉点对邻近的交叉点进行标记,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// 对某一块棋进行膨胀
func do_group_dilation(num : Int) {
for x in 1...13 {
for y in 1...13 {
if labelNodes[x,y] != num {
continue
}
var xx = x - 1
if xx > 0 && dilationNodes[xx,y] == 0 {
dilationNodes[xx,y] = 1
}
xx = x + 1
if xx <= 13 && dilationNodes[xx,y] == 0 {
dilationNodes[xx,y] = 1
}
var yy = y - 1
if yy > 0 && dilationNodes[x,yy] == 0 {
dilationNodes[x,yy] = 1
}
yy = y + 1
if yy <= 13 && dilationNodes[x,yy] == 0 {
dilationNodes[x,yy] = 1
}
}
}
}

结果如下图:

3. 得到2号块所有气的标记

将第一步的所有空闲点与第二步相邻交叉点的相乘得到这块棋子的气的数量
代码如下:

1
2
3
4
5
6
7
8
9
// 标记气的交叉点
func do_cal_alive() {
//
for x in 1...13 {
for y in 1...13 {
aliveNodes[x,y] = emptiesNodes[x,y] * dilationNodes[x,y]
}
}
}

结果如下图,这块棋子一共3口气:

这里有一张动图,这里需要注意白棋的分块的序号变化
因为吃子的变化导致分块序号重新计算: