如何为任何给定坐标找到正确的邻居?

更新:这个问题正在寻求如何获得任何给定坐标的一组邻居的指导。

我创建了一个包含坐标的二维数组,

int[][] coordinates= { { -1, -1 }, { -1, 0 }, { -1, +1 }, { 0, -1 }, { 0, +1 }, { +1, -1 }, { +1, 0 }, { +1, -1 } }; 

如您所知,这些是坐标(0,0)的邻居。

现在我试图实现一个方法,它接受两个参数(int positionX, int positionY) ,并使用输入参数值coordiante(x,y)作为起始坐标,并找到该坐标的所有邻居。

我在考虑这样的事情:

  int getNearCoordinates(int positionX, int positionY) { for (int[] coordinate: coordinates) { //I am not sure what to do after this } } 

我试图使用一个循环从我创建的2d数组获取单独的坐标,我被困在这里。 我如何找到一种方法来正确找到positionX和positionY的邻居?

什么是邻居?

下图中的所有橙色点都是Origin的邻居(0,0) 在此处输入图像描述

我建议

  • 使用专用Coordinate )而不是int[] 。 这使您的代码更容易扩展(第三维等)或更改(使用double而不是int等)。 在示例中,您可以看到一个可模拟的类 – 这会阻碍代码产生副作用。
  • 使用Collection而不是Array 。 这使得处理更容易(您可以简单地addremove项目)
  • 使用java8-Streaming-API 。 它快速闪电,使您的代码更易读。

其他想法:

  • 你甚至可以让getNearCoordinates成为Coordinate类的一部分。 这将使new Coordinate(27,35).getNearCoordinates()可用。
  • 您可以使用Map而不是将xy存储在单独的字段中。 这会使您的代码更难理解 – 但会减少重复的代码。
  • 你也可以使用两个嵌套循环for (int x = -1; x <= 1; x++) for (int y = -1; y <= 1; y++) use(new Coordinate(x,y)) 生成方向集合for (int x = -1; x <= 1; x++) for (int y = -1; y <= 1; y++) use(new Coordinate(x,y)) 。 这将使您的代码更清晰 ,但可能更难理解。

示例代码:

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

没有Java8-streaming API的相同行为将如下所示:

 /** @return a collection of eight nearest coordinates near origin */ Collection getNearCoordinates(Coordinate origin) { Collection neighbours = new ArrayList<>(); for (Coordinate direction : coordinates) neighbours.add(origin.move(direction)); return neighbours; } 

如果此表达式为真,则两个点A(x1,y1)B(x2,y2)是邻居:

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

这里如果两个差都等于零,那么A等于B.

这不是实现它的最佳方式(使用int []作为点),这个答案的目的是显示算法

如果你在谈论一个无界的飞机,那么你将总是有8个点,所以你可以通过以下方式实现它:

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

如果飞机有界 ,这次使用ArrayList 会变得更有趣

 public List getNeighbours(int x, int y, int minX, int maxX, int minY, int maxY) { List ret = new ArrayList(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; } 

后者适用于任何一点,也可以在飞机外或边界处。

这取决于您如何定义邻居。 下面的代码将测试坐标,并为对角线以及水平和垂直邻居返回true。

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

确保导入java.lang.Math

打印坐标当然只是一个例子,但可能对调试很有用。

这看起来很明显,但您可以复制coordinates ,并将给定坐标的x和y值添加到每个坐标的坐标,使用for循环的示例。