计算机围棋/处理落子
外观
< 计算机围棋
现在我们已经能够检测合法落子,下一步就是实际处理合法落子,通过将新棋子添加到棋盘上,移除任何被吃掉的棋子,并更新禁手点。我们已经能够检测到何时发生吃子
} 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; }
如果您想要本章中使用的所有源代码的副本,这些代码已准备好编译和运行,您可以从这里下载示例代码副本。