计算机围棋/处理落子
外观
< 计算机围棋
现在我们已经能够检测合法落子,下一步就是实际处理合法落子,通过将新棋子添加到棋盘上,移除任何被吃掉的棋子,并更新禁手点。我们已经能够检测到何时发生吃子
} else if (getColor(neighbor) == c.opposite()) {
// if any neighbor is an enemy
// and that enemy is in atari
if (inAtari(neighbor)) {
suicide = false;
}
}
现在我们只需要更新这段代码以移除被吃掉的棋子。到目前为止,应该很明显,表示链的方式将非常有用。让我们修改之前getLiberties()代码,以返回一个链而不是一组气
private Set<Point> getChainPoints(Board b, Point p) {
Set<Point> stones = new HashSet<Point>();
stones.add(p);
Color myColor = b.getColor(p);
Color floodfillColor = myColor.opposite();
b.setColor(p, floodfillColor);
List<Point> neighbors = b.getNeighbors(p);
for (Point neighbor : neighbors) {
if (b.getColor(neighbor) == myColor) {
if (!stones.contains(neighbor)) {
stones.addAll(getChainPoints(b, neighbor));
}
}
}
return stones;
}
给定构成特定链的一组棋子,我们也可以很容易地获得与该链相邻的空点的集合,并构造一个包含这两个集合的对象。
private Chain getChain(Point p) {
Set<Point> stones = getChainPoints(clone(), p);
Set<Point> liberties = new HashSet<Point>();
for (Point stone : stones) {
for (Point point : getNeighbors(stone)) {
if (getColor(point) == EMPTY) {
liberties.add(point);
}
}
}
return new Chain(stones, liberties);
}
修改后的从棋盘上移除被吃掉棋子的代码现在变得非常简单
} else if (getColor(neighbor) == c.opposite()) {
// if any neighbor is an enemy
// and that enemy is in atari
Chain enemy = getChain(neighbor);
if (enemy.inAtari()) {
suicide = false;
// remove the enemy stones from the board
for (Point point : enemy) {
setColor(point, EMPTY);
capturedStones.add(point);
}
}
}
通过将被吃掉的棋子保存在一个集合中,我们现在可以轻松地更新禁手点。
// If this move captured exactly one stone, that stone is the new ko point
if (capturedStones.size() == 1) {
koPoint = capturedStones.iterator().next();
} else {
koPoint = null;
}
如果您想要本章中使用的所有源代码的副本,这些代码已准备好编译和运行,您可以从这里下载示例代码副本。