[英]More efficient way to check neighbours in a two-dimensional array in Java
嘿,对于我的一些大学作业,我发现需要检查二维数组(网格)中的相邻单元格。 我使用的解决方案有点使用异常,但是我正在寻找一种方法来清理它,而无需像某些同学一样加载if
语句。 我当前的解决方案是
for ( int row = 0; row < grid.length; row++ ) {
for ( int col = 0; col < grid.length; col++ ) {
// this section will usually be in a function
// checks neighbours of the current "cell"
try {
for ( int rowMod = -1; rowMod <= 1; rowMod++ ) {
for ( int colMod = -1; colMod <= 1; colMod++ ) {
if ( someVar == grid[row+rowMod][col+colMod] ) {
// do something
}
}
}
} catch ( ArrayIndexOutOfBoundsException e ) {
// do nothing, continue
}
// end checking neighbours
}
}
我不禁想到使用异常来使我的代码工作的原因导致效率低下,所以我正在寻找有关如何在不牺牲可读性的情况下如何从代码中消除对异常的依赖的建议,以及我将如何做的建议。此代码段通常更有效。 提前致谢。
你可以试试看 首先确定网格的大小,假设其为8 X 8并分配MIN_X = 0,MIN_Y = 0,MAX_X = 7,MAX_Y = 7
您当前的职位由thisPosX,thisPosY表示,然后尝试以下操作:
int startPosX = (thisPosX - 1 < MIN_X) ? thisPosX : thisPosX-1;
int startPosY = (thisPosY - 1 < MIN_Y) ? thisPosY : thisPosY-1;
int endPosX = (thisPosX + 1 > MAX_X) ? thisPosX : thisPosX+1;
int endPosY = (thisPosY + 1 > MAX_Y) ? thisPosY : thisPosY+1;
// See how many are alive
for (int rowNum=startPosX; rowNum<=endPosX; rowNum++) {
for (int colNum=startPosY; colNum<=endPosY; colNum++) {
// All the neighbors will be grid[rowNum][colNum]
}
}
您可以分2个循环完成它。
所以row
和col
当前包含我要检查其邻居的单元格的坐标。 因此,如果我有一个名为START_OF_GRID
的类变量,其中包含0
,则解决方案如下:
int rowStart = Math.max( row - 1, START_OF_GRID );
int rowFinish = Math.min( row + 1, grid.length - 1 );
int colStart = Math.max( col - 1, START_OF_GRID );
int colFinish = Math.min( col + 1, grid.length - 1 );
for ( int curRow = rowStart; curRow <= rowFinish; curRow++ ) {
for ( int curCol = colStart; curCol <= colFinish; curCol++ ) {
// do something
}
}
为什么不能在访问数组之前检查row + rowMod和col + colMod的有效性?
就像是:
r=row+rowMod;
c=col+colMod;
if (r < 0 || c < 0 || r >= grid.length || c >= grid.length) continue;
或者(不继续 ):
if (r >= 0 && c >= 0 && r < grid.length && c < grid.length &&
someVar == grid[r][c]) { /* do something */ }
这个怎么样:
private static void printNeighbours(int row, int col, int[][] Data, int rowLen, int colLen)
{
for(int nextR=row-1; nextR<=row+1; nextR++)
{
if(nextR<0 || nextR>=rowLen)
continue; //row out of bound
for(int nextC=col-1; nextC<=col+1; nextC++)
{
if(nextC<0 || nextC>=colLen)
continue; //col out of bound
if(nextR==row && nextC==col)
continue; //current cell
System.out.println(Data[nextR][nextC]);
}
}
}
基本原则是不要访问超出范围的内容-因此要么保护范围,要么首先不要超出范围。 也就是说,从您不会立即越界的地方开始,然后在越界之前停止。
for ( int row = 1; row < grid.length - 1; row++ ) {
for ( int col = 1; col < grid.length - 1; col++ ) {
// this section will usually be in a function
// checks neighbours of the current "cell"
for ( int rowMod = -1; rowMod <= 1; rowMod++ ) {
for ( int colMod = -1; colMod <= 1; colMod++ ) {
if ( someVar == grid[row+rowMod][col+colMod] ) {
// do something
}
}
}
// end checking neighbours
}
}
就像您当前的代码一样,这不一定能正确处理边缘条件-也就是说,它将3x3网格应用于矩阵中适合矩阵的所有位置,但不会在3x3网格缩小时将其缩小到2x2、2x3或3x2网格在矩阵的边缘。 但是,这将允许主体中的一种方法检查3x3网格以观察矩阵中的每个单元。
如果我正确地理解了您的代码,并且正确地猜到了您的担忧,那么您将避免在目标单元格位于网格的一侧时避免检查不存在的邻居。 一种可能适合您的应用程序或可能不适合您的应用程序的方法是在整个网格周围放置一个1单元宽的边框。 然后,您可以在此扩展网格的内部运行循环,并且您检查的所有单元格都有4个邻居(如果计算对角相邻的单元格,则为8个)。
private void fun(char[][] mat, int i, int j){
int[] ith = { 0, 1, 1, -1, 0, -1 ,-1, 1};
int[] jth = { 1, 0, 1, 0, -1, -1 ,1,-1};
// All neighbours of cell
for (int k = 0; k < 8; k++) {
if (isValid(i + ith[k], j + jth[k], mat.length)) {
//do something here
}
}
}
private boolean isValid(int i, int j, int l) {
if (i < 0 || j < 0 || i >= l || j >= l)
return false;
return true;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.