我正在创建一个像应用程序一样的扫雷,并且有一些代码旨在检查一个非开采的空间周围有多少个地雷。我已经为此创造了一些东西
int count = 0;
if(model.get(i-1, j-1) == MinerGridCo.UNTURNED_MINE){ count++;}
if(model.get(i, j-1) == MinerGridCo.UNTURNED_MINE){ count++;}
if(model.get(i-1, j) == MinerGridCo.UNTURNED_MINE){ count++;}
if(model.get(i+1, j) == MinerGridCo.UNTURNED_MINE){ count++;}
if(model.get(i, j+1) == MinerGridCo.UNTURNED_MINE){ count++;}
if(model.get(i-1, j+1) == MinerGridCo.UNTURNED_MINE){ count++;}
if(model.get(i+1, j-1) == MinerGridCo.UNTURNED_MINE){ count++;}
if(model.get(i+1, j+1) == MinerGridCo.UNTURNED_MINE){ count++;}
String mineNum = String.valueOf(count);
cell[i][j].setText(mineNum);
然而,当试图获得围绕电路板边缘的矿号时,这会产生错误。有什么有用的方法可以避免这种情况吗?
在尝试下面的建议之后。我仍然得到越界错误。任何人都有任何建议,如果有人想自己编译https://github.com/phillolivercomp/MineSweeper.git
,这里就是回购答案 0 :(得分:2)
帮自己一个忙,然后创建model.countUnturnedMinesAround(i,j)
。然后在模型内你有一些选择。
您可以创建视图看不到的额外行/列,以便您可以轻松处理逐个索引。
或者你可以编写一个函数private Cell getCell(i,j)
,它会在i和j超出范围时返回默认的空单元格。
或者,当i或j离开网格时,您可以让boolean hasUnturnedMine(i,j)
返回false。
答案 1 :(得分:2)
您可以避免与循环重复:
for (int iOffset = -1; iOffset <= 1; iOffset++) {
for (int jOffset = -1; jOffset <= 1; jOffset++) {
if (iOffset != 0 || jOffset != 0) {
if (isInGrid(i + iOffset, j + jOffset) &&
model.get(i + iOffset, j + jOffset) == MinerGridCo.UNTURNED_MINE) {
count++;
}
}
}
}
使用@ Emrakul回答建议的isInGrid
函数(我实际上将范围检查和UNTURNED_MINE检查合并到一个hasUnturnedMine
函数中,如@ Arkadiy的答案中所述。
答案 2 :(得分:1)
使用短路,并编写一个函数isInGrid(int x, int y)
,用于检查位置是否在网格中。
public boolean isInGrid(int x, int y) {
//Check if a position is valid in the grid
if(i < 0 || j < 0) return false;
if(i >= WIDTH || j >= HEIGHT) return false;
return true;
}
...
if(isInGrid(i-1, j-1) && model.get(i-1, j-1) == MinerGridCo.UNTURNED_MINE) count++;
if(isInGrid(i+1, j+1) && model.get(i+1, j+1) == MinerGridCo.UNTURNED_MINE) count++;
//Repeat for each location you want to check
如果第一个条件isInGrid(i-1, j-1)
不为真,那么条件将退出而不运行[condition]
语句。通过这种方式,如果否则[condition]
会失败,则会阻止if
执行。
这称为&#34;短路&#34; - 如果已经知道代码不会运行,那么会导致isInGrid
条件检查退出的优化。您可以在要评估的每个语句之前放置其中一个get
检查,如果该位置不在网格中,则不会执行{{1}}。
答案 3 :(得分:0)
创建一行功能:
boolean checkBounds(int i, int j) {
//TODO
}
然后在进行模型查找之前检查
答案 4 :(得分:0)
另一种方法可能是让方法isBorder(int i,int j)让你知道你是否在界限上。如果它不是边框,您知道可以安全地检查周围的所有方块(i,j)。如果它在边框上,您可以计算它是左/右/上/下边框还是4(不超过2)的某种组合,然后选中相应的框。
免责声明:我假设您已经进行了检查,以确保(i,j)是网格上的有效位置。无论您的实施如何,都应该对此进行检查答案 5 :(得分:0)
通过更好地构建代码,有更好的方法可以做到这一点。但是,这是您具体问题的答案:
在Java中忽略异常的方法是使用try-catch块。这允许您尝试运行代码块,捕获任何抛出的异常,然后决定如何处理它们(包括忽略它们)。
假设您的out of bounds异常来自model.get()调用,您可以忽略它们:
int count = 0;
try
{
if(model.get(i-1, j-1) == MinerGridCo.UNTURNED_MINE){ count++;}
if(model.get(i, j-1) == MinerGridCo.UNTURNED_MINE){ count++;}
if(model.get(i-1, j) == MinerGridCo.UNTURNED_MINE){ count++;}
if(model.get(i+1, j) == MinerGridCo.UNTURNED_MINE){ count++;}
if(model.get(i, j+1) == MinerGridCo.UNTURNED_MINE){ count++;}
if(model.get(i-1, j+1) == MinerGridCo.UNTURNED_MINE){ count++;}
if(model.get(i+1, j-1) == MinerGridCo.UNTURNED_MINE){ count++;}
if(model.get(i+1, j+1) == MinerGridCo.UNTURNED_MINE){ count++;}
}
catch (IndexOutOfBoundsException ex)
{
// Do nothing
}
String mineNum = String.valueOf(count);
cell[i][j].setText(mineNum);
但是,遇到异常时,将跳过try块中的所有后续代码。这绝对不是你想要的,因为你会错过检查一些邻接。 相反,您需要为每次调用model.get()执行try-catch。最好通过创建一个布尔函数来实现,如:
// Change method visibility and signature accordingly to match your code
public static boolean tileHasMine(int x, int y)
{
try
{
if (model.get(x, y) == MinerGridCo.UNTURNED_MINE)
{
return true;
}
}
catch (IndexOutOfBoundsException ex)
{
// Do Nothing
}
return false;
}
然后你的支票看起来像:
int count = 0;
if(tileHasMine(i-1, j-1)){ count++;}
if(tileHasMine(i, j-1)){ count++;}
if(tileHasMine(i-1, j)){ count++;}
if(tileHasMine(i+1, j)){ count++;}
if(tileHasMine(i, j+1)){ count++;}
if(tileHasMine(i-1, j+1)){ count++;}
if(tileHasMine(i+1, j-1)){ count++;}
if(tileHasMine(i+1, j+1)){ count++;}
String mineNum = String.valueOf(count);
cell[i][j].setText(mineNum);
或者,您可以编写一个布尔函数,该函数首先检查块是否超出模型的边界,甚至在尝试读取之前,这可能是更好的方法。但我认为这就是你所要求的。