【问题标题】:Finding valid neighbors in 2D array在二维数组中查找有效邻居
【发布时间】:2013-10-19 00:05:22
【问题描述】:

所以,我有一个 4x4 二维数组(它总是这些尺寸)。从数组上的一个位置开始,一些行和列,我想找到它的所有有效邻居。到目前为止,我的实现非常笨拙。

//add row
    if ( !((row + 1) > 3)) {
        //do stuff
    }
    //sub row
    if ( !((row - 1) < 0)) {
        //do stuff
    }
    //add col
    if ( !((col + 1) > 3)) {
        //do stuff
    }
    //sub col
    if ( !((col - 1) < 0)) {
        //do stuff
    }
... and so on

这是残酷的。当我从知道元素的位置开始时,我觉得我不需要检查每个邻居。有什么想法吗?

【问题讨论】:

  • 取决于//do stuff 是什么。可以全部改成一行吗?
  • 如果一个位置是一个有效的邻居(到达做的东西),它只是将行、列位置添加到列表中。或者更具体地说,创建一个 Location(row,col) 对象,并将其添加到列表中。
  • Unsolicited => 我会尽量让您的代码保持正面;意思是否定你的!s。例如,if(!((col-1)&lt;0)) 变为 if((col-1)&gt;=0)

标签: java arrays 2d


【解决方案1】:

对于(x,y) 维度的任何二维数组cellValues[][],以下代码可用于获取任何单元格(i,j) 的所有8 个邻居。代码默认返回0

public static ArrayList<Integer> getNeighbors(int i, int j, int x, int y, int[][] cellValues) {
    ArrayList<Integer> neighbors = new ArrayList<>();

    if(isCabin(i, j, x, y)) {
        if(isCabin(i + 1, j, x, y))
            neighbors.add(cellValues[i+1][j]);
        if(isCabin(i - 1, j, x, y))
            neighbors.add(cellValues[i-1][j]);
        if(isCabin(i, j + 1, x, y))
            neighbors.add(cellValues[i][j+1]);
        if(isCabin(i, j - 1, x, y))
            neighbors.add(cellValues[i][j-1]);
        if(isCabin(i - 1, j + 1, x, y))
            neighbors.add(cellValues[i-1][j+1]);
        if(isCabin(i + 1, j - 1, x, y))
            neighbors.add(cellValues[i+1][j-1]);
        if(isCabin(i + 1, j + 1, x, y))
            neighbors.add(cellValues[i+1][j+1]);
        if(isCabin(i - 1, j - 1, x, y))
            neighbors.add(cellValues[i-1][j-1]);
    }
    return neighbors;
}

public static boolean isCabin(int i, int j, int x, int y) {
    boolean flag = false;
    if (i >= 0 && i <= x && j >= 0 && j <= y) {
        flag = true;
    }
    return flag; 
}

【讨论】:

    【解决方案2】:

    以下是我的做法:一种获取有效邻居的 x,y 对列表的方法,给定任意 [x,y] 点并推广到任何数组大小:

    public List<int[]> getNeighbors(x, y, maxX, maxY) {
        neighbors = new ArrayList<int[]>;
        if x > 0:
            neighbors.add({x-1, y});
        if y > 0:
            neighbors.add({x, y-1});
        if x < maxX:
            neighbors.add({x+1, y});
        if x < maxY:
            neighbors.add({x, y+1});
        return neighbors;
    }
    
    [...]
    
    for (int[] coords : getNeighbors(x, y, 4, 4)) {
        // do stuff
    }
    

    【讨论】:

    • 我喜欢这个主意。不过,对于非常大的矩阵可能不是最有效的。
    • 为什么不呢?无论矩阵有多大,它的运行时间都是 O(1),只要您只需要单个单元格的邻居即可。
    • 是的,没错,我想我只是看看它与他们自己的条件相比,在这种情况下只有更多的东西。我不得不说,无论// do stuff 做什么,它都是最易读的语法。
    • 实际上,我看到将它们添加到列表中是 OP 告诉你的,所以没关系。
    【解决方案3】:

    不幸的是,通过编写代码,您是在告诉计算机该做什么,而计算机除了您告诉它的内容之外什么都不知道。

    我猜你可以用非标准的循环逻辑稍微自动化这种事情:

    for (int coff = -1; coff < 3; coff += 2) {
        for (int roff = -1; roff < 3; roff += 2) {
    
            if (    col + coff >= 0 &&
                    col + coff < array.length &&
                    row + roff >= 0 &&
                    row + roff < array[row].length) {
    
                // do stuff with array[col + coff][row + roff]
    
            }
        }
    }
    

    该循环结构会将列和行偏移量从 -1 翻转为 1,然后在第 3 次迭代中变为 3 时中断。

    但请注意,在您的代码中,检查 !(stuff) > 4 会给您一个 ArrayIndexOutOfBounds 异常,因为请记住最后一个索引是 4 - 1。

    【讨论】:

      【解决方案4】:

      什么是有效邻居?

      如果您只想检索数组边界内单元格的所有邻居(包括对角线),这就足够了。

      public List<Element> getNeighbors( int x, int y ) {
          List<Element> neighbors = new ArrayList<>();
      
          for( int i = -1; i <= 1; ++i ) {
              for( int j = -1; j <= 1; ++j ) {
                  if( i == 0 && j == 0 ) {
                      continue;
                  }
                  if( i + x >= 0 && i + x < array.length &&
                      j + y >= 0 && j + y < array[0].length ) {
                          // we found a valid neighbor!
                          neighbors.add( array[i][j] );
                  }
              }
          }
      
          return neighbors;
      }
      

      【讨论】:

        【解决方案5】:

        我会做的方式是有一个单独的方法。

        public void example(int changeSign, boolean shouldCheckRow,boolean shouldCheckColumn){
            int num = 4;
            if(changeSign < 0)
                num = 0;
            if(shouldCheckRow)
                //adding a negative is the same as subtracting so if you add -1, you're really subtracting by one.
        
                if(!((row + changeSign) < num))
                    //do stuff
            else
                if(!((col + changeSign) < num))
                    //do stuff
        }
        

        方法调用将是

        public static void main(String args[]){
            int shouldTestRight = 1;
            int shouldTestLeft = -1;
            int shouldTestUp = 1;
            int shouldTestDown = -1;
            // so if you want to test up or right, the first parameter should be positive
            // if you want to test for down or left, the first parameter should be negative
            // this is because the negative will flip the sign.
            // if you should change the row, the second parameter should be true
            // if you should change the column, the third parameter should be true.
            example(shouldTestRight,true,false);
            example(shouldTestLeft,true,false);
            example(shouldTestUp,false,true);
            example(shouldTestDown,false,true);
        }
        

        当然,您不必在调用的方法中包含额外的整数,但我这样做是为了增加代码的可读性。

        【讨论】:

          【解决方案6】:

          这是我的解决方案:

          public int[4][4] array2d;
          //don't forget to fill it!
          
          private void adjustNeighbors(int xCoord, int yCoord) {
          
              for (int yi = y-1; yi <= yCoord+1; yi++) {         //loop through the neighbors
          
                  for (int xi = x-1; xi <= xCoord+1; xi++) {
          
                      try {
          
                          if (!(xCoord != xi && yCoord != yi)) {
                              array2d[y][x]++;  //do whatever you want to all the neighbors!
                          } 
          
                      } catch (Exception e) {
                          // something is out of bounds
                      }
          
                  }
          
              }
          
          }
          

          【讨论】:

          • 您的代码中不存在变量 x 和 y,但您将 y - 1 和 x - 1 分配给 for 循环中的索引。没有意义。
          【解决方案7】:
          public class FindingNeighboursInMatrix {
          
          public static void main(String[] args) {
              int array[][] = { { 1, 2, 3, 4 }, 
                                { 5, 6, 7, 8 }, 
                                { 9, 10, 11, 12 } };
          
              for (int i = 0; i < array.length; i++) {
          
                  for (int j = 0; j < array[0].length; j++) {
          
                      System.out.println("neightbours of " + array[i][j]);
                      int neb[] = findneighbours(i, j, array);
                      for (int k = 0; k < neb.length; k++) {
                          if (neb[k] != -1) {
                              System.out.print(" " + neb[k] + ",");
                          }
                      }
                      System.out.println();
                  }
          
              }
          
          }
          
          public static int[] findneighbours(int i, int j, int matrix[][]) {
              int neb[] = new int[8];
              // top row
              neb[0] = getvalue(i - 1, j - 1, matrix);
              neb[1] = getvalue(i - 1, j, matrix);
              neb[2] = getvalue(i - 1, j + 1, matrix);
          
              // left element
          
              neb[3] = getvalue(i, j - 1, matrix);
          
              // right element
          
              neb[4] = getvalue(i, j + 1, matrix);
          
              // bottom row
              neb[5] = getvalue(i + 1, j - 1, matrix);
              neb[6] = getvalue(i + 1, j, matrix);
              neb[7] = getvalue(i + 1, j + 1, matrix);
          
              return neb;
          
          }
          
          public static int getvalue(int i, int j, int matrix[][]) {
              int rowSize = matrix.length;
              int colSize = matrix[0].length;
          
              if (i < 0 || j < 0 || i > rowSize - 1 || j > colSize - 1) {
                  return -1;
              }
              return matrix[i][j];
          }}
          

          【讨论】:

            猜你喜欢
            • 2010-10-13
            • 2017-10-04
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-05-06
            • 1970-01-01
            相关资源
            最近更新 更多