禁手的判定较为复杂,设计一个判断禁手的算法既要分析构成它的棋型又要找到合适的搜索方法。
首先分析棋型。
先考虑构成长连禁手的棋型,构成长连的棋型较简单,可归纳为一种,即相连后形成六子或更多相连。一旦发现产生此棋型,即判为长连禁手。
再考虑构成四四禁手、三三禁手的棋型。要判断下某一子是否构成四四禁手(或三三禁手),只需判断下这一子后是否产生两个或两个以上的冲四或活四(或活三)即可。所以归结起来,要正确判断四四禁手、三三禁手就是要正确判断冲四、活四和活三。
考虑冲四、活四和活三的定义。冲四是只有一个点可以成五的四,这里我们将那个点称为关键点。同样,构成活四的有两个关键点,构成活三的有一个关键点。如图
11
,
a,b
两点是其构成活四的关键点,又如图
12
,
a
点是其构成活三的关键点。
![]() |
![]() |
以下是对各棋型和关键点的分析。
1
、活四:
归结起来构成活四的只有一种棋型
,
如图
13
![]() |
这种棋型真正构成活四的条件是左右两空位(即
a,b
点)必须是黑棋可下的点,也就是在
a,b
点下黑子后都不会构成禁手。
2
、冲四:
形成冲四有两种棋型,如图
14
和图
15
![]() |
![]() |
这两种棋型真正构成冲四的条件是中间的空位(即
a
点)必须是黑棋可下的点,也就是在
a
点下子后不会构成禁手。
3
、活三:
形成活三有两种棋型,如图
16
和图
17
![]() |
![]() |
其中,
a
点是关键点,
b,c
点可以是边界、无子或白色棋子,但不能是黑色棋子。
这两种棋型真正构成活三的条件是
a
点必须是黑棋可下的点,也就是在
a
点下子后不会构成禁手,
m,n
两点不用管是否构成禁手,因为当
a
点放入黑子后,不管在
m
点还是
n
点放黑子,就会形成五连,即获胜,不构成禁手。
所以我们要判断一种棋型是否构成冲四、活四或活三,需要在已判断它是可能的冲四、活四或活三的棋型的基础上判断它的关键点是否可落黑色棋子,也就是判断关键点是否不会构成新的禁手点,这一步在程序中可以用递归实现。
棋型分析完成,我们就要据此考虑选择合适的算法。
基于禁手分析所需的精确度,我们在棋盘盘面搜索时,需要记录与待判断点相邻的连续黑色棋子数,并记录之后的连续空子数,并记录再之后的连续黑子数,和再之后的连续空子数,以及再之后的连续黑子数。所以可以说搜索的深度要达到
5
层。
在判断关键点的可下性时,选用递归的方法来判断其是否不是禁手点。
于是最后我们可以得出禁手判定算法的思路。
第一步:将待判断点放入黑棋子;
第二步:搜索待判断点周边棋盘;
第三步:还原棋盘;
第四步:利用搜索结果依次对各方向进行分析,判断黑棋放入后所产生的棋型是否形成长连或形成可能构成活四、冲四、活三的棋型。若形成长连,判定为禁手,返回长连禁手标识。若形成可能是活四、冲四、活三的棋型,判断关键点是否可下,若不可下,该棋型统计数加1,反之,则对下一个方向进行判断,直到各个方向分析结束。
第五步:若活四、冲四棋型的统计数大于1,返回四四禁手标识,若活三棋型的统计数大于1,返回三三禁手标识。其余情况返回非禁手标识。
源代码:







