How to find correct neighbors for any giving coordinate?

戏子无情 提交于 2019-12-04 04:45:14

I'd recommend to

  • Use a dedicated class (Coordinate) instead of int[]. This makes your code easier to extend (3rd dimention, etc) or to change (using double instead of int, etc.). In the example you can see an imutable class - this hinders code to have side effects.
  • Use Collection instead of Array. This makes handling much easier (you can simply add and remove items)
  • Use java8-Streaming-API. It is lightning fast and makes your code better readable.

Additional ideas:

  • You could even make getNearCoordinates part of the Coordinate class. This would make new Coordinate(27,35).getNearCoordinates() available.
  • Instead of storing x and y in separate fields you could also use a Map<Axis, Integer>. This would make your code a little bit harder to understand - but would reduce duplicated code.
  • You could also generate the collection of directions by using two nested loops for (int x = -1; x <= 1; x++) for (int y = -1; y <= 1; y++) use(new Coordinate(x,y)). This would make your code cleaner, but might be harder to understand.

Example code:

import java.util.*;
import java.util.stream.Collectors;

public class Snippet {

    // make a class to be more flexible
    class Coordinate {

        // final fields are making this an "imutable"
        final int x;
        final int y;

        /** constructor to take coordinate values */
        Coordinate(int x, int y) {
            this.x = x;
            this.y = y;
        }

        /** moves this coordinate by another coordinate */
        Coordinate move(Coordinate vector) {
            return new Coordinate(x + vector.x, y + vector.y);
        }
    }

    /** using Collection instead of Array makes your live easier. Consider renaming this to "directions". */
    Collection<Coordinate> coordinates = Arrays.asList(
            new Coordinate( -1, -1 ), // left top
            new Coordinate( -1,  0 ), // left middle
            new Coordinate( -1, +1 ), // left bottom
            new Coordinate(  0, -1 ), // top
            new Coordinate(  0, +1 ), // bottom
            new Coordinate( +1, -1 ), // right top
            new Coordinate( +1,  0 ), // right middle
            new Coordinate( +1, +1 )  // right bottom
            );

    /** @return a collection of eight nearest coordinates near origin */
    Collection<Coordinate> getNearCoordinates(Coordinate origin) {
        return
                // turn collection into stream
                coordinates.stream()

                // move the origin into every direction
                .map(origin::move)

                // turn stream to collection
                .collect(Collectors.toList());
    }

}

Same behaviour without Java8-streaming API would look like this:

/** @return a collection of eight nearest coordinates near origin */
Collection<Coordinate> getNearCoordinates(Coordinate origin) {
    Collection<Coordinate> neighbours = new ArrayList<>();

    for (Coordinate direction : coordinates)
        neighbours.add(origin.move(direction));

    return neighbours;
}

Two points A(x1,y1), B(x2,y2) are neighbours if this expression is true:

 Math.abs(x1-x2) <= 1 && Math.abs(y1-y2) <= 1 

Here if both differences are equal to zero then A equals B.

This is not the best way to implement it (using int[] for points), the purpose of this answer is to show the algorithms.

If you are talking about an unbounded plane then you will always have 8 points, so you could implement it the following way:

// first point index, 2nd: 0 = x, 1 = y
public int[][] getNeighbours(int x, int y) {
   int[][] ret = new int[8][2];
   int count = 0;
   for (int i = -1; i <= 1; i++)
      for (int j = -1; j <= 1; j++) {
         if (i == 0 && j == 0)
            continue;
         ret[count][0] = x + i;
         ret[count++][1] = y + j;
      }
   return ret;
}

It gets more interesting if the plane is bounded, using an ArrayList this time:

public List<int[]> getNeighbours(int x, int y, int minX, int maxX, int minY, int maxY) {
   List<int[]> ret = new ArrayList<int[]>(8); // default initial capacity is 100
   for (int i = Math.max(x - 1, minX); i <= Math.min(x + 1, maxX); i++)
      for (int j = Math.max(y - 1, minY); j <= Math.min(y + 1, maxY); j++) {
         if (i == x && j == y)
            continue;
         ret.add(new int[] {i, j});
      }
   return ret;
}

The latter will work for any point, also outside of the plane or just at the border.

That depends on how you define a neighbour. The code below will test the coordinates and return true for the diagonal as well as horizontal and vertical neighbours.

if (Math.abs(coordinate[0] - positionX) <= 1 && Math.abs(coordinate[1] - positionY) <= 1)
{
    System.out.println(Arrays.toString(coordinate));
}

make sure to import java.lang.Math

Printing of the coordinates is just an example of course, but may be useful for debugging.

It may seem obvious, but you could duplicate coordinates, and add the given coordinate's x and y values to those of each coordinate, fit example using a for loop.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!