在二维数组中查找有效的邻居

4

因此,我有一个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 是什么。你能把它都改成一行吗? - Christian Ternus
如果一个位置是有效的邻居(可以到达),它就会将行、列位置添加到列表中。更具体地说,它会创建一个 Location(row,col) 对象,并将其添加到列表中。 - rhl13
不请自来 => 我建议您尽量保持代码的正面性,即避免使用 !。例如,if(!((col-1)<0)) 可以改写为 if((col-1)>=0) - ChiefTwoPencils
7个回答

3

对于任何一个二维数组cellValues[][],其维度为(x,y),下列代码可用于获取任何单元格(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; 
}

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,然后在第三次迭代时停止。

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


2
这是我的做法:编写一个方法,该方法获取x,y坐标对的列表以获得有效邻居,给定任意的[x,y]点并推广到任何数组大小:
```HTML

这是我的做法:编写一个方法,该方法获取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
}

我喜欢这个想法。但对于非常大的矩阵可能不是最有效的。 - Radiodef
为什么不呢?只要你只需要单个单元格的邻居,无论矩阵有多大,它的运行时间都是O(1)。 - Christian Ternus
是的,没错,我猜我只是将它与单独的条件进行了比较,在这种情况下有更多的元素。我必须说,不管 // do stuff 的功能是什么,它都是最可读的语法。 - Radiodef
实际上,我看把它们添加到列表中是OP告诉你应该做的,所以不用管它了。 - Radiodef

2

什么构成有效的邻居?

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

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

1
这是我的解决方案:

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,但你在for循环中将y-1和x-1赋值给索引。这毫无意义。 - luckyguy73

1
我会这样做,就是使用一个单独的方法。
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);
}

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

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接