我试图找到离玩家最近的第 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);
希望对您有所帮助!