如何为任何给定坐标找到正确的邻居?
How to find correct neighbors for any giving coordinate?
更新:此问题正在寻求有关如何为任何给定坐标获取一组邻居的指导。
我创建了一个包含坐标的二维数组,
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
}
}
我正在尝试使用循环从我创建的二维数组中获取单个坐标,但我被困在这里。我如何找到合适的方法来找到 positionX 和 positionY 的邻居?
什么是邻居?
下图中所有橙色点都是原点的邻居 (0,0)
两个点 A(x1,y1), B(x2,y2) 是邻居,如果这个表达式为真:
Math.abs(x1-x2) <= 1 && Math.abs(y1-y2) <= 1
此处如果两个差值都为零,则 A 等于 B。
我会推荐
- 使用专用的 class (
Coordinate
) 而不是 int[]
。这使您的代码更易于扩展(第三维等)或更改(使用 double
而不是 int
等)。在示例中,您可以看到 imutable class - 这会阻碍代码产生副作用。
- 使用
Collection
而不是 Array
。这使得处理更容易(您可以简单地 add
和 remove
项)
- 使用java8-Streaming-API。它快如闪电,让您的代码更具可读性。
其他想法:
- 您甚至可以使
getNearCoordinates
成为坐标 class 的一部分。这将使 new Coordinate(27,35).getNearCoordinates()
可用。
- 除了在单独的字段中存储
x
和 y
,您还可以使用 Map<Axis, Integer>
。这会使您的代码更难理解 - 但会减少重复代码。
- 您还可以使用两个嵌套循环 生成 路线集合
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<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());
}
}
没有 Java8-streaming API 的相同行为将如下所示:
/** @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;
}
这取决于你如何定义邻居。下面的代码将测试对角线以及水平和垂直邻居的坐标和 return true。
if (Math.abs(coordinate[0] - positionX) <= 1 && Math.abs(coordinate[1] - positionY) <= 1)
{
System.out.println(Arrays.toString(coordinate));
}
确保导入 java.lang.Math
坐标的打印当然只是一个例子,但可能对调试有用。
这不是实现它的最佳方式(使用 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<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;
}
后者适用于任何点,也适用于平面外或边界处。
这看起来很明显,但您可以复制 coordinates
,并将给定坐标的 x 和 y 值添加到每个坐标的值,使用 for 循环拟合示例。
更新:此问题正在寻求有关如何为任何给定坐标获取一组邻居的指导。
我创建了一个包含坐标的二维数组,
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
}
}
我正在尝试使用循环从我创建的二维数组中获取单个坐标,但我被困在这里。我如何找到合适的方法来找到 positionX 和 positionY 的邻居?
什么是邻居?
下图中所有橙色点都是原点的邻居 (0,0)
两个点 A(x1,y1), B(x2,y2) 是邻居,如果这个表达式为真:
Math.abs(x1-x2) <= 1 && Math.abs(y1-y2) <= 1
此处如果两个差值都为零,则 A 等于 B。
我会推荐
- 使用专用的 class (
Coordinate
) 而不是int[]
。这使您的代码更易于扩展(第三维等)或更改(使用double
而不是int
等)。在示例中,您可以看到 imutable class - 这会阻碍代码产生副作用。 - 使用
Collection
而不是Array
。这使得处理更容易(您可以简单地add
和remove
项) - 使用java8-Streaming-API。它快如闪电,让您的代码更具可读性。
其他想法:
- 您甚至可以使
getNearCoordinates
成为坐标 class 的一部分。这将使new Coordinate(27,35).getNearCoordinates()
可用。 - 除了在单独的字段中存储
x
和y
,您还可以使用Map<Axis, Integer>
。这会使您的代码更难理解 - 但会减少重复代码。 - 您还可以使用两个嵌套循环 生成 路线集合
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<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());
}
}
没有 Java8-streaming API 的相同行为将如下所示:
/** @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;
}
这取决于你如何定义邻居。下面的代码将测试对角线以及水平和垂直邻居的坐标和 return true。
if (Math.abs(coordinate[0] - positionX) <= 1 && Math.abs(coordinate[1] - positionY) <= 1)
{
System.out.println(Arrays.toString(coordinate));
}
确保导入 java.lang.Math
坐标的打印当然只是一个例子,但可能对调试有用。
这不是实现它的最佳方式(使用 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<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;
}
后者适用于任何点,也适用于平面外或边界处。
这看起来很明显,但您可以复制 coordinates
,并将给定坐标的 x 和 y 值添加到每个坐标的值,使用 for 循环拟合示例。