我正在尝试实施一种算法来清除我的Go游戏中的死石。
我听说洪水填充是最好的,因为递归使用它会更有效,更容易实现。
我在代码中使用它时遇到了麻烦,并且想知道我应该如何实现它。
这是我的课程之一,非常自我解释。
import java.io.*;
public class GoGame implements Serializable {
int size;
char[][] pos; // This is the array that stores whether a Black (B) or White (W) piece is stored, otherwise its an empty character.
public GoGame(int s){
size = s;
}
public void init() {
pos = new char[size][size];
for (int i=0;i<size;i++) {
for (int j=0;j<size;j++) {
pos[i][j] = ' ';
}
}
}
public void ClearAll() {
for (int i=0;i<size;i++) {
for (int j=0;j<size;j++) {
pos[i][j] = ' ';
}
}
}
public void clear(int x, int y) {
pos[x][y]=' ';
}
public void putB(int x, int y) { //places a black stone on the board+array
pos[x][y]='B';
floodfill(x,y,'B','W');
}
public void putW(int x, int y) { //places a white stone on the board+array
pos[x][y]='W';
floodfill(x,y,'W','B');
}
public char get(int x, int y) {
return pos[x][y];
}
public void floodfill(int x, int y, char placed, char liberty){
floodfill(x-1, y, placed, liberty);
floodfill(x+1, y, placed, liberty);
floodfill(x, y-1, placed, liberty);
floodfill(x, y+1, placed, liberty);
}
}
x
和y
是方格的坐标,placed
是放下的石头的字符,liberty
是另一个字符
任何帮助都会很棒!
答案 0 :(得分:2)
虽然其他答案在技术上是正确的,但您也缺少与go相关的更多逻辑。你需要做的是,我认为(在B行动中):
for each W neighbour of the move:
check that W group to see if it has any liberties (spaces)
remove it if not
洪水填充对于找到一组石头的范围很有用,但是你的日常工作需要的不仅仅是那些(我在这里简化,并试图猜测这个例程的用途 - 请参阅下面的评论这个答案)。
鉴于上述情况,识别群组中所有宝石的洪水填充将是这样的(请注意,它使用第二个阵列进行填充,因为您不希望仅更改pos
找一个小组):
public void findGroup(int x, int y, char colour, char[][] mask) {
// if this square is the colour expected and has not been visited before
if (pos[x][y] == colour && mask[x][y] == ' ') {
// save this group member
mask[x][y] = pos[x][y];
// look at the neighbours
findGroup(x+1, y, colour, mask);
findGroup(x-1, y, colour, mask);
findGroup(x, y+1, colour, mask);
findGroup(x, y-1, colour, mask);
}
}
您可以调用它来识别单个组(并将其复制到掩码中),这样它将帮助您识别与B移动相邻的W组的成员(例如),但它只是一小部分你需要的总逻辑。
最后,请注意,如果你想对一组中的每一块石头做些什么,你有两个选择。您可以调用上面的例程,然后循环mask
以查找该组,或者您可以将您想要执行的操作直接放在例程中(在这种情况下,您仍然使用mask
控制测试&& mask[x][y] == ' '
中洪水填充的程度,但不要将其作为结果使用 - 所有工作都在例程返回时完成。
(按照所有规则编程要正确处理的东西,实际上非常复杂 - 你需要做很多工作......:o)
答案 1 :(得分:0)
我会使用虚假证明。以下是我找到捕获的石头的方法:
private static final int SIZE = 8;
private static final int VACANT = 0; //empty point
private static final int MY_COLOR = 1; //Black
private static final int ENEMY_COLOR = 2; //White
private static final int CHECKED = 50; //Mark for processed points
private static final int OUT = 100; //points out of the board
private static boolean isCaptured(int col, int row, int[][] board) {
boolean result = !isNotCaptured(col, row, board);
cleanBoard(board);
return result;
}
private static boolean isNotCaptured(int col, int row, int[][] board) {
int value = board[col][row];
if (!(value == MY_COLOR || value == CHECKED))
return true;
int top = row < SIZE - 1 ? board[col][row + 1] : OUT;
int bottom = row > 0 - 1 ? board[col][row - 1] : OUT;
int left = col > 0 ? board[col - 1][row] : OUT;
int right = col < SIZE - 1 ? board[col + 1][row] : OUT;
if (top == VACANT || right == VACANT || left == VACANT || bottom == VACANT)
return true;
board[col][row] = CHECKED;
return (top == MY_COLOR && isNotCaptured(col, row + 1, board))
|| (bottom == MY_COLOR && isNotCaptured(col, row - 1, board))
|| (left == MY_COLOR && isNotCaptured(col - 1, row, board))
|| (right == MY_COLOR && isNotCaptured(col + 1, row, board));
}
private static void cleanBoard(int[][] board) {
for (int i = 0; i < SIZE; i++) {
for (int j = 0; j < SIZE; j++) {
if (board[i][j] == CHECKED)
board[i][j] = MY_COLOR;
}
}
}
然后你可以调用这样的方法:
isCaptured(5, 4, board)
答案 2 :(得分:0)
我认为BFS对于这种情况会更好,因为你需要首先探索邻居,这样如果捕获了其中任何一个,那么捕获该点。
答案 3 :(得分:0)
正如其他人指出的那样,Go中也有一个“ ko规则”,这大致意味着您在捕获单个石头(简化)时不允许立即捕获。总之,您可能要为此使用现有的库。
我建议使用 brugo 存储库,该存储库在maven中可用。
<!-- https://mvnrepository.com/artifact/be.brugo/brugo -->
<dependency>
<groupId>be.brugo</groupId>
<artifactId>brugo</artifactId>
<version>0.1.0</version>
</dependency>
大致如此。 (警告:代码未经测试)
// create a starting position
Position position = new Position(boardSize, komi);
// play a move
Intersection whereToPlay = Intersection.valueOf(4,4);
IntStatus colorToPlay = IntStatus.BLACK;
Position position2 = position.play(whereToPlay, colorToPlay);
// watch the result.
IntStatus[][] matrix = position2.getMatrix()
它还包含要导出到“加载/保存SGF”的对象。 SGF文件的加载不仅支持UTF-8
,而且还支持亚洲编码。下面的屏幕快照显示了实现自己的难度:
如果您还计划使用javafx,请运行此演示:brugo.go.ui.javafx.goban.GobanComponentDemo
足够让您入门。
http://www.brugo.be是一个PHP网站,大约在2008年左右创建,它是一个在线的joseki字典,显然需要一些代码才能使用Go职位。因此,所有这些都是用PHP编写的。大约一年后,它开始使用一些Java applet(当时还是“还可以”),这将使浏览位置更加容易。因此,用于go逻辑的代码已移植到Java。
后来,人们做出了一些努力,也将其用于AI和客户端/服务器应用程序,但没有成功。大约在这个时候,Java代码得到了重大改进,以支持不同的文件编码。
但是在2015年左右的某个地方,代码被移植到javascript,2017年左右被移植到打字稿,以尝试升级brugo网站。再次没有直接成功。
在2018年左右的某个时候,有计划将Java代码用于特定的开放源代码项目(再次与AI相关),但这没有成功。但是正是在那时,它才被集中在Maven中。
由于LeeLa Zero的成功,在这段时间里,开源Go项目大量涌现。这也是为什么将brugo的Java代码开源的原因。
2019年初http://www.zbaduk.com推出(现在是非官方的),它重新使用了BruGo的打字稿代码,并且还将LeeLa Zero项目用于AI。