在Java中检查二维数组中的邻居的更有效方法

嘿所有,对于我的一些大学作业,我发现需要检查二维arrays(网格)中的相邻单元格。 我使用的解决方案是使用exception的一些黑客攻击,我正在寻找一种方法来清理它,而不if像我的一些同学那样加载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 } } 

我不禁想到使用exception来使我的代码工作原因的低效率,所以我正在寻找关于如何在不牺牲可读性的情况下从代码中消除对exception的依赖的建议,以及我如何制作这段代码通常更有效率。 提前致谢。

你可以试试这个。 首先确定网格的大小让我们说它是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个循环中完成它。

因此rowcol当前包含我要检查邻居的单元格的坐标。 因此,如果我有一个名为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 */ } 

基本原则是不访问超出界限的东西 – 所以要么保护边界,要么首先不要超出范围。 也就是说,从一个你不会立即走出界限并在你出界之前停下来的地方开始。

 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网格时在矩阵的边缘。 然而,它将允许主体中的方法检查3×3网格以观察矩阵中的每个单元。

如果我正确理解您的代码,并且正确地猜测您的问题,那么当您感兴趣的单元格位于网格的一个边缘时,您会尝试避免检查不存在的邻居。 一种方法可能适用于您的应用,也可能不适合您的应用,即在网格中放置1个单元的宽边框。 然后,您可以在此扩展网格的内部运行循环,并且您检查的所有单元格都有4个邻居(如果计算对角相邻的单元格,则为8个邻居)。

这个怎么样:

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