JackBum
JackBum

Reputation: 18

How to get all the neihbors neighbors of a point in a 2d array?

I am trying to get all the neighbors of a combination of simple one character strings in a 2d array. Meaning, my output looks like this currently in a 3x5:

A B C
D E F
A S D 
F S A
G S A

So the neighbor of (1,0) should be = A B E S A . Currently I have the following:

public void getNeighborsOfPoint(int x, int y) {

        for (int xx = -1; xx <= 1; xx++) {
            for (int yy = -1; yy <= 1; yy++) {
                if (xx == 0 && yy == 0) {
                    continue; // You are not neighbor to yourself
                }
                if (Math.abs(xx) + Math.abs(yy) > 1) {
                    continue;
                }
                if (isOnMap(x + xx, y + yy)) {
                    System.out.println(grid[x+xx][y+yy]);
                }
            }
        }
   

 public boolean isOnMap(int x, int y) {
        return x >= 0 && y >= 0 && x < length && y < width;
    }

However it is only returning A E A in the example I provided.(it is not returning the ones cross-wise) What is the right code to make it work? Note that the input will not always be 3 x 5. It may be a lot of different combination of x and y s.

Upvotes: 0

Views: 401

Answers (4)

dariosicily
dariosicily

Reputation: 4527

If you want to use 2d arrays with variable number of rows and columns you have to pass them as parameters in your's isOnMap method like below:

public static boolean isOnMap(int x, int y, int length, int width) {
    return x >= 0 && y >= 0 && x < length && y < width;
}

You can handle the special cases of your 2d array (when one or both rownumber and columnnumber of your element are equal to 0) rewriting your getNeighborsOfPoint method in this way:

public static void getNeighborsOfPoint(int x, int y, char[][] grid) {
    final int length = grid.length;
    final int width = grid[0].length;

    if (isOnMap(x, y, length, width)) {

        for (int i = Math.max(0, x - 1); i < Math.min(length, x + 2); ++i) {
            for (int j = Math.max(0, y - 1); j < Math.min(width, y + 2); ++j) {

                if (i != x || j != y) {
                    System.out.println(grid[i][j]);
                }
            }
        }
    }
}

Upvotes: 0

Badda
Badda

Reputation: 1369

In a loop, the continue keyword means that you will skip to the next iteration of the loop. In your case, you have :

            if (Math.abs(xx) + Math.abs(yy) > 1) {
                continue;
            }
            if (isOnMap(x + xx, y + yy)) {
                System.out.println(grid[x+xx][y+yy]);
            }

So if the first condition is verified, you will not print any answer, meaning that your program won't consider A(xx, yy) to be a neighbord.

In your ABESA example, B and S are ignored because of this.

Upvotes: 0

Chad
Chad

Reputation: 61

The diagonals aren't included because of this code:

if (Math.abs(xx) + Math.abs(yy) > 1) {
    continue;
}

When it's on the diagonal Math.abs(xx) == 1 && Math.abs(yy) == 1. So their sum will be greater than 1. You're skipping over the diagonals by having this code here.

Upvotes: 2

tplusk
tplusk

Reputation: 1007

The reason you're not getting the diagonals in your current group is that second if statement. You need to cover, for example, (2, 1) which is when xx is 1 and yy is 1. But abs(1) + abs(1) = 2 and 2 > 1, so you don't include it.

As a refactoring exercise, it might be a little cleaner if you have the inside of that for loop simplified to one conditional.

if (expression) { 
    continue 
}; 
// other stuff

is equivalent to

if (!expression) {
  // other stuff.
}

And for you, expression (in psuedocode) is not(xx=0 and yy=0) and isOnMap(xx, yy)

Upvotes: 0

Related Questions