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

时间:2015-08-01 17:21:00

标签: java algorithm coordinates

更新:此问题正在寻求有关如何为任何给定坐标获取一组邻居的指导。

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

 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的邻居?

什么是邻居?

下图中的所有橙色点都是原点(0,0)的邻居 enter image description here

5 个答案:

答案 0 :(得分:6)

我建议

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

其他想法:

  • 您甚至可以使getNearCoordinates成为Coordinate类的一部分。这将使new Coordinate(27,35).getNearCoordinates()可用。
  • 您可以使用x,而不是将yMap<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;
}

答案 1 :(得分:4)

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

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

如果两个差异均等于零,则 A 等于 B

答案 2 :(得分:1)

这不是实现它的最好方法(使用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;
}

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

答案 3 :(得分:0)

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

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

确保导入java.lang.Math

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

答案 4 :(得分:0)

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