查找两个数据类型的第 n 个最近的对象



我试图找到离玩家最近的第 n 个对象,环顾四周并得出结论,2D ArrayList 或列表似乎是我需要存储对象 id 及其与玩家的距离,然后按升序排序。但是,我不确定如何使用列表实现这一点。我目前确实有工作代码来查找最近的对象,但是如果不使用大量变量,找到第 n 个似乎要棘手得多。

下面的问题是我见过的最接近的答案 - 但是他们使用两个字符串,而不是我需要的两个不同的值,例如 Object 和 int。

如何仅按第一个元素对 2D 数组列表<字符串>进行排序

List<ArrayList<GameObject>> nearest = new ArrayList<ArrayList<GameObject>>();
nearest.add(new ArrayList<GameObject>(Arrays.asList(instance, int))); //Adds a new instance and it's distance to the player.

目前我收到一个错误,不允许在数组中同时使用对象和 int,并且我似乎无法为这两种类型定义它。

假设您有一个游戏对象的集合(Set,List等(:

Collection<GameObject> gameObjects = ...;

在某处,您还有一种用于计算一个游戏对象到玩家的距离的方法。我假设它返回一个 int:

public int computeDistanceToPlayer(GameObject gameObject) {
...
}

您希望按这些游戏对象与玩家的距离对这些对象进行排序,以便获得第 n 个更近的对象。最简单的方法是对对象进行排序。例如:

List<GameObject> sortedGameObjects = 
gameObjects.stream()
.sorted(Comparator.comparingInt(gameObject -> computeDistanceToPlayer(gameObject)))
.collect(Collectors.toList());

然后,您可以从该列表中获取第 n 个元素。

您甚至可以直接从流中获取第 n 个元素:

GameObject nthCloserGameObject = 
gameObjects.stream()
.sorted(Comparator.comparingInt(gameObject -> computeDistanceToPlayer(gameObject)))
.skip(n - 1)
.findFirst()
.orElse(null);

这就是您所需要的,但是,如果距离计算成本高昂(需要长时间、昂贵的计算(,那么它并不是真正的最佳选择,因为它会多次计算同一游戏对象的距离:每次在排序过程中都会将其与另一个游戏对象进行比较。因此,如果要避免这种情况,可以先计算所有距离并将其与游戏对象相关联,然后对结果进行排序:

public class GameObjectWithDistance {
private final GameObject gameObject;
private final int distance;
// constructor, getters omitted for brevity
}

现在,您只需要将每个游戏对象包装在 GameObjectWithDistance 中,并对结果进行排序:

GameObject nthCloserGameObject = 
gameObjects.stream()
.map(gameObject -> new GameObjectWithDistance(gameObject, computeDistanceToPlayer(gameObject)))
.sorted(Comparator.comparingInt(GameObjectWithDistance::getDistance))
.skip(n - 1)
.findFirst()
.map(GameObjectWithDistance::getGameObject)
.orElse(null);

现在,如果你不熟悉流和lambda,你可以使用循环,列表和比较器类来做到这一点,没关系。重要的是逻辑,以及意识到您不需要任何类似内容的2D列表。

如果我正确理解您的问题,您需要将距离与GameObject一起临时存储并按距离排序。 之后,您将需要获得第 n 个GameObject

您可以将"游戏对象"和"距离"存储在Map<GameObject, Integer>中,并且可以使用Java 8轻松地对它们进行排序。之后,您可以从映射中获取keySet作为列表并获取第n个。

例如,您有一个地图: (为简单起见,我假设游戏对象构造函数采用整数,例如(

Map<GameObject, Integer> map = new HashMap<GameObject, Integer>();
map.put(new GameObject(1), 2);
map.put(new GameObject(3), 1);
map.put(new GameObject(2), 5);

要获取地图,请按距离排序:

HashMap<GameObject, Integer> sortedMap = map.entrySet().stream()
.sorted(Map.Entry.<GameObject, Integer>comparingByValue())
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
(oldValue, newValue) -> oldValue, LinkedHashMap::new));

现在如果我们打印这个地图的值,我们得到:

System.out.println(collect.values());

输出:

[1, 2, 5]

所以现在你的sortedMap的KeySet是GameObject的排序列表,从中你可以很容易地得到第n个:

List<GameObject> keySet = (List<GameObject>) collect.keySet();
keySet.get(n-1);

希望对您有所帮助!

最新更新