我正在尝试用Java重新创建棋盘游戏“go”。我目前正在研究捕获系统。基本上,一旦石头四面被敌人的石头包围(对角线不计算),你就会移走那块石头。如下面的截图。
如果连接了多个相同的宝石,则必须围绕所有开放的边。如下面的截图。
在这两种情况下,此时应移除黑色宝石。此链接更多地解释了捕获石头的规则。 societies.cam。 AC。英国/cugos/go/rules_03.html
我被告知最好使用递归来做到这一点。在对递归进行一些研究后,我设法编写了一些代码。但它不起作用。它似乎只是在游戏的第二步中发现敌人的石头。每次在我的鼠标中放置一块石头时,我都会调用我的方法。
public static boolean checkCapture(int x, int y)
{
{
if ((board[x][y + 1] != move) && (board[x][y + 1] != 0)) //bellow
{
System.out.println("enemy is bellow");
if (checkCapture(x, y + 1))
board[x][y] = 0;
} else if (board[x][y + 1] == 0)
{
return false;
}
if ((board[x][y - 1] != move) && (board[x][y - 1] != 0)) //above
{
System.out.println("enemy is above");
if (checkCapture(x, y - 1))
board[x][y] = 0;
} else if (board[x][y - 1] == 0)
{
return false;
}
if ((board[x + 1][y] != move) && (board[x + 1][y] != 0)) // right
{
System.out.println("enemy is right");
if (checkCapture(x + 1, y))
board[x][y] = 0;
} else if (board[x + 1][y] == 0)
{
return false;
}
if ((board[x - 1][y] != move) && (board[x - 1][y] != 0)) //left
{
System.out.println("enemy is left");
if (checkCapture(x - 1, y))
board[x][y] = 0;
} else if (board[x - 1][y] == 0)
{
return false;
}
}
return true;
}
我的int x是我的列,我的int是我的行,move是我的变量,它保持轮到它(1 =黑色,2 =白色)board是我的2d数组,它保存所有石头的位置董事会。
答案 0 :(得分:2)
我认为递归使这个解决方案变得更加复杂。如果我要实现这样的东西,我会采取以下步骤:
查找已连接的宝石组。如果你可以通过两只眼睛检测一个群体是否还活着,你可以将其限制为龙。
对于每组连接的宝石,纵向和横向计算自由度。 (自由是与相连的一组石头相邻的未占据位置。)如果自由数为0,则该组被捕获。
如果您在移动后检查捕获,那么您实际上只需要检查与最近移动相邻的连接组,而不是所有连接组。
答案 1 :(得分:1)
首先,从显式开始,关于你的功能是什么。
/**
* Checks to see if the grid point passed in is captured.
* @param...(you should say what your params are here
**/
public static boolean checkCapture(int x, int y) {
//some code
}
这很重要:如果此函数检查网格点是否正在捕获其他任意点,该怎么办?此外,我们立即看到一个问题......由谁捕获?每当解决递归问题时,你需要理解基本情况:这里没有没有被敌人占据的垂直或水平相邻区域。
因此,我们必须检查以查看特定颜色:
/**
* Checks to see if the grid point passed in is captured.
* @param...(you should say what your params are here
**/
public static boolean checkCapture(int x, int y) {
if (!isOccupied(x,y)) {//writing this function should be trivial
return false;//can't be captured; no one is there!
}
Color color = getColor(x,y);//similarly, get the color of whoever is there.
Status status = checkFlanked(x, y, color);
if (status = Status.FLANKED) {
return true;
}
}
private static Status checkFlanked(int x, int y, Color color) {
//check to see that this location is valid for the board
//check to see if this square is occupied at all
//if it is not, return LIBERTY (an empty space means no capture, right?)
//if it is, is it occupied by the opposite color? --> Return a FLANKED result!
//if it is, is it occupied by the same color? --> recurse!
}
现在我们已经解决了我们的问题!并且很容易看出基本案例是如何解决的:如果广场未被占用,则它不能是侧翼...因此它返回LIBERTY
结果。如果它被相反的颜色占据,那么这个方块就在你最初检查的任何一个侧面。唯一困难的部分是检查是否,如果被原始颜色占用,任何其他地点是否有自由。
//get all valid adjacent locations
//call checkFlanked on those locations.
//If any return LIBERTY, return LIBERTY. Otherwise return FLANKED.
(注意:为了清楚起见,我假设LIBERTY
和FLANKED
被定义为枚举。)
我希望这可以帮助您以更明智的方式解决问题。记住:当你使用递归时,你关心两种情况:基本情况和'+1迭代'情况。请注意,即使使用上述内容,您也必须解决一些问题:
其他一些有趣的问题是:
答案 2 :(得分:-1)
我有一些代码可以让你玩和捕捉石头。请参阅此答案:https://gamedev.stackexchange.com/questions/23291/go-game-placing-stones-on-grid-intersections/23406#23406
诀窍是跟踪连续的石块,然后在每次移动后检查以查看该移动是否捕获了一块。
还有担心的问题。
答案 3 :(得分:-3)
在这种情况下递归的问题是很容易陷入无限循环。检查两块石头,检查正确的石头将检查左石头将再次检查右边等。您需要跟踪已经检查过的石头。你将需要通过一些你已经检查过的石头状态。