patternjavaMinor
Getting the neighbors of a Point in a 2D grid
Viewed 0 times
thegridpointgettingneighbors
Problem
I am trying to find an algorithm to find all the defined neighbors of a 2D
Here is my existing code:
What I'm looking for mainly is better readability.
Point (efficiently would be nice, but does not make much of a difference).Here is my existing code:
private static ArrayList getNeighborsOfPoint(int i, int j) {
ArrayList neighbors = new ArrayList();
if (CONSIDER_CORNERS) {
if (i = 1 && j >= 1 && array[i][j] != 0) {
neighbors.add(new Point(i-1, j-1));
}
if (i = 1 && j >= 0 && array[i][j] != 0) {
neighbors.add(new Point(i-1, j+1));
}
if (i = 0 && j >= 1 && array[i][j] != 0) {
neighbors.add(new Point(i+1, j-1));
}
if (i = 0 && j >= 0 && array[i][j] != 0) {
neighbors.add(new Point(i+1, j+1));
}
}
if (i = 1 && j >= 0 && array[i][j] != 0) {
neighbors.add(new Point(i-1, j));
}
if (i = 0 && j >= 1 && array[i][j] != 0) {
neighbors.add(new Point(i, j-1));
}
if (i = 0 && j >= 0 && array[i][j] != 0) {
neighbors.add(new Point(i, j+1));
}
if (i = 0 && j >= 0 && array[i][j] != 0) {
neighbors.add(new Point(i+1, j));
}
return neighbors;
}CONSIDER_CORNERS is a boolean that is settable by the user, and Point is just a simple class that has an x and y int value. rows and cols are the number of elements in each of the two dimensions.What I'm looking for mainly is better readability.
Solution
Improvements
Code
In this code, I have not added your
Going the extra mile
Having this method, it is very easy to add support for some very crazy neighbor styles. This might not fit your game, but using crazy neighbor styles can transform a concept into an entirely different game.
For example, take Minesweeper Flags (where the objective is to find the mines and not avoid them).
We all know what an 8 means, right? 8 mines around the number, plain and simple.
Now, what if we transform the way we look for neighbors? To what I call "Chess style" (based on how a Knight moves in Chess).
This "simple" change leads to a much greater challenge when playing, leading to all kinds of fun.
The change required for this is really simple, extract a
Using this method, the special case logic for handling corners and the self neighbor is no longer necessary.
Of course, using the ordinary neighbor set is also possible with this method:
- Use
xandynames to avoid confusion about what isiand what isj
- I personally find it preferrable to put the
xparameter first
rowsandcolsshould not be static variables, so neither should this method
- Use a double for-loop to loop over the neighbors
- Declare by interface and not implementation (use
Listwhen possible)
- Use some maths to check if you're at a corner or not
Code
private List getNeighborsOfPoint(int x, int y) {
List neighbors = new ArrayList();
for (int xx = -1; xx 1) {
continue;
}
if (isOnMap(x + xx, y + yy)) {
neighbors.add(new Point(x + xx, y + yy));
}
}
}
return neighbors;
}
public boolean isOnMap(int x, int y) {
return x >= 0 && y >= 0 && x < cols && y < rows;
}In this code, I have not added your
array[i][j] != 0 check, but that can easily be added into isOnMap, although you could then rename it to isValidNeighbor or something.Going the extra mile
Having this method, it is very easy to add support for some very crazy neighbor styles. This might not fit your game, but using crazy neighbor styles can transform a concept into an entirely different game.
For example, take Minesweeper Flags (where the objective is to find the mines and not avoid them).
We all know what an 8 means, right? 8 mines around the number, plain and simple.
Now, what if we transform the way we look for neighbors? To what I call "Chess style" (based on how a Knight moves in Chess).
This "simple" change leads to a much greater challenge when playing, leading to all kinds of fun.
The change required for this is really simple, extract a
NEIGHBOR_SET array:private static final Point[] NEIGHBOR_SET = new Point[]{ new Point(-2, -1), new Point(-2, 1),
new Point(-1, -2), new Point(-1, 2), new Point(1, -2), new Point(1, 2), new Point(2, -1), new Point(2, 1) };
private List getNeighborsOfPoint(int x, int y) {
List neighbors = new ArrayList();
for (Point neighbor : NEIGHBOR_SET) {
if (isOnMap(x + neighbor.x, y + neighbor.y)) {
neighbors.add(new Point(x + neighbor.x, y + neighbor.y));
}
}
return neighbors;
}Using this method, the special case logic for handling corners and the self neighbor is no longer necessary.
Of course, using the ordinary neighbor set is also possible with this method:
private static final Point[] NEIGHBOR_SET = new Point[]{ new Point(-1, -1), new Point(-1, 0),
new Point(-1, 1), new Point(0, -1), new Point(0, 1), new Point(1, -1), new Point(1, 0), new Point(1, 1) };Code Snippets
private List<Point> getNeighborsOfPoint(int x, int y) {
List<Point> neighbors = new ArrayList<Point>();
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 (!CONSIDER_CORNERS && Math.abs(xx) + Math.abs(yy) > 1) {
continue;
}
if (isOnMap(x + xx, y + yy)) {
neighbors.add(new Point(x + xx, y + yy));
}
}
}
return neighbors;
}
public boolean isOnMap(int x, int y) {
return x >= 0 && y >= 0 && x < cols && y < rows;
}private static final Point[] NEIGHBOR_SET = new Point[]{ new Point(-2, -1), new Point(-2, 1),
new Point(-1, -2), new Point(-1, 2), new Point(1, -2), new Point(1, 2), new Point(2, -1), new Point(2, 1) };
private List<Point> getNeighborsOfPoint(int x, int y) {
List<Point> neighbors = new ArrayList<Point>();
for (Point neighbor : NEIGHBOR_SET) {
if (isOnMap(x + neighbor.x, y + neighbor.y)) {
neighbors.add(new Point(x + neighbor.x, y + neighbor.y));
}
}
return neighbors;
}private static final Point[] NEIGHBOR_SET = new Point[]{ new Point(-1, -1), new Point(-1, 0),
new Point(-1, 1), new Point(0, -1), new Point(0, 1), new Point(1, -1), new Point(1, 0), new Point(1, 1) };Context
StackExchange Code Review Q#68627, answer score: 7
Revisions (0)
No revisions yet.