跳到內容

計算機圍棋/處理落子

來自華夏公益教科書,開放的書籍,為開放的世界

處理落子

[編輯 | 編輯原始碼]

現在我們已經能夠檢測合法落子,下一步就是實際處理合法落子,透過將新棋子新增到棋盤上,移除任何被吃掉的棋子,並更新禁手點。我們已經能夠檢測到何時發生吃子

} 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;
}

如果您想要本章中使用的所有原始碼的副本,這些程式碼已準備好編譯和執行,您可以從這裡下載示例程式碼副本

華夏公益教科書