Java 获取列表中距离其他列表中的点最远的点
我有一份球员名单和积分名单。每个玩家都有一个角色对象,每个角色都有一个位置。一个角色有很多生命,当他被杀死时,只要他还有生命,他就会在离其他玩家最远的产卵点重生。为此,我创建了以下代码:Java 获取列表中距离其他列表中的点最远的点,java,Java,我有一份球员名单和积分名单。每个玩家都有一个角色对象,每个角色都有一个位置。一个角色有很多生命,当他被杀死时,只要他还有生命,他就会在离其他玩家最远的产卵点重生。为此,我创建了以下代码: for (Player spawnPlayer : players) { if (spawnPlayer.getCharacter().getCanSpawn()) { System.out.println("works"); List<Integer> distanc
for (Player spawnPlayer : players) {
if (spawnPlayer.getCharacter().getCanSpawn()) {
System.out.println("works");
List<Integer> distanceArrayList = new ArrayList();
for (Point point : map.getSpawnPoints()) {
int distance = 0;
for (Player player : players) {
if (player != spawnPlayer && player.getCharacter().getLives() > 0 && !player.getCharacter().getCanSpawn()) {
distance += Math.sqrt(Math.pow(point.x - player.getCharacter().getPosition().x, 2)
+ Math.pow(point.y - player.getCharacter().getPosition().y, 2));
}
}
distanceArrayList.add(distance);
}
Point spawnPoint = map.getSpawnPoints().get(distanceArrayList.indexOf(Collections.max(distanceArrayList)));
spawnPlayer.getCharacter().spawn(spawnPoint);
}
}
我建议您使用局部变量来记住当前最大值和相应的位置。通过避免搜索列表,您将获得性能。这将更改代码,如下所示:
public void SpawnPlayers()
{
for (Player spawnPlayer : players)
{
if (spawnPlayer.getCharacter().getCanSpawn())
{
int maxDistance = 0;
Point spawnPoint = null;
for (Point point : map.getSpawnPoints())
{
int sumDistancesFromOthers = 0;
for (Player player : players)
{
if (player != spawnPlayer && player.getCharacter().getLives() > 0 && !player.getCharacter().getCanSpawn())
{
sumDistancesFromOthers += Math.sqrt(Math.pow(point.x - player.getCharacter().getPosition().x, 2)
+ Math.pow(point.y - player.getCharacter().getPosition().y, 2));
}
}
if (maxDistance < sumDistancesFromOthers || spawnPoint == null)
{
maxDistance = sumDistancesFromOthers;
spawnPoint = point;
}
}
spawnPlayer.getCharacter().spawn(spawnPoint);
}
}
}
for (Player spawnPlayer : players) {
if (spawnPlayer.getCharacter().getCanSpawn()) {
System.out.println("works");
int maxDistance = 0;
Point spawnPoint = null;
for (Point point : map.getSpawnPoints()) {
int sumDistancesFromOthers = 0;
for (Player player : players) {
if (player != spawnPlayer && player.getCharacter().getLives() > 0 && !player.getCharacter().getCanSpawn()) {
sumDistancesFromOthers += Math.sqrt(Math.pow(point.x - player.getCharacter().getPosition().x, 2)
+ Math.pow(point.y - player.getCharacter().getPosition().y, 2));
}
}
if (maxDistance < sumDistancesFromOthers || spawnPoint == null) {
maxDistance = sumDistancesFromOthers;
spawnPoint = point;
}
}
spawnPlayer.getCharacter().spawn(spawnPoint);
}
}
for(玩家:玩家){
if(spawnPlayer.getCharacter().getCanSpawn()){
System.out.println(“工程”);
int最大距离=0;
点=空;
对于(点:map.getSpawnPoints()){
int sumDistancesFromOthers=0;
用于(玩家:玩家){
如果(player!=spawnPlayer&&player.getCharacter().getlifes()>0&&player.getCharacter().getCanSpawn()){
sumdancesfromothers+=Math.sqrt(Math.pow(point.x-player.getCharacter().getPosition().x,2)
+pow(point.y-player.getCharacter().getPosition().y,2));
}
}
if(maxDistance
我添加了测试spawnPoint==null
,以确保退出循环时spawnPoint
不会null
希望这将有助于
杰夫
------------更新------------
我更正了上面的代码片段,将与其他玩家的距离之和作为最大化距离的定义加以考虑。建议的代码更改:
for (Player spawnPlayer : players) {
if (spawnPlayer.getCharacter().getCanSpawn()) {
System.out.println("works");
int maxDistance = 0;
Point currentSpawnPoint = null;
for (Point point : map.getSpawnPoints()) {
int distance = 0;
for (Player player : players) {
if (player != spawnPlayer && player.getCharacter().getLives() > 0 && !player.getCharacter().getCanSpawn()) {
distance += Math.sqrt(Math.pow(point.x - player.getCharacter().getPosition().x, 2)
+ Math.pow(point.y - player.getCharacter().getPosition().y, 2));
}
}
if(distance>maxDistance){
maxDistance = distance;
currentSpawnPoint = Point;
}
}
spawnPlayer.getCharacter().spawn(spawnPoint);
}
}
推理:记住距离是没有必要的,依赖列表索引不是清理代码的方法(它们可能会改变) 如果以下假设成立,我认为您的代码片段没有问题:
Character.getCanSpawn()
意味着Character.getlifes()>0
Character.spawn(spawnPoint)
确保Character.getCanSpawn()==false
(post条件)最初你仍然可以比最佳繁殖更接近:假设你随机为第一个角色选择一个繁殖位置,第二个角色只在最佳位置w.r.t.第一个角色。但是,现在可能有一个更适合第一个字符的位置。我有点太懒了,无法“调试”您的代码,这就是为什么我创建了下面的代码片段 反正
- 我建议您将代码分成更小的部分。例如,我将代码移动到
类来计算两点之间的距离点
- 此外,下面的代码
位置if (maxDistance < sumDistancesFromOthers || spawnPoint == null) { maxDistance = sumDistancesFromOthers; spawnPoint = point; }
繁殖点public class Position { private int x; private int y; public Position(Position position) { if (position != null) { this.x = position.x; this.y = position.y; } } public Position(int x, int y) { this.x = x; this.y = y; } public int getX() { return this.x; } public int getY() { return this.y; } /** * Calculates the distance between this position and the given position. * @param anotherPosition The position to compare the current position with. * @return The distance as a double. */ public double getDistance(Position anotherPosition) { double xDistance = Math.abs(Math.pow(this.x - anotherPosition.x, 2)); double yDistance = Math.abs(Math.pow(this.y - anotherPosition.y, 2)); return Math.sqrt(xDistance + yDistance); } }
主要问题是:public class SpawnPoint { private Position position; public SpawnPoint(Position position) { this.position = position; } public SpawnPoint(int x, int y) { this(new Position(x, y)); } public Position getPosition() { return new Position(this.position); } }
public static void main(String[] args) { // Create some spawnpoints... List<SpawnPoint> spawnPoints = new ArrayList<SpawnPoint>() {{ add(new SpawnPoint(0, 0)); add(new SpawnPoint(2, 0)); add(new SpawnPoint(0, 5)); add(new SpawnPoint(2, 5)); }}; // Create some players Player playerA = new Player(new Position(0, 0)); Player playerB = new Player(new Position(4, 1)); Player playerC = new Player((Position) null); // A null position means that the player is dead. // Add the players to the list of players... List<Player> players = new ArrayList<Player>() {{ add(playerA); add(playerB); add(playerC); }}; // Spawn playerC (which is currently dead and need to be respawned) // and return the best spawn point as defined by the OP SpawnPoint sp = playerC.spawn(spawnPoints, players); // Print the position System.out.println(sp.getPosition()); }
我保持它的简单,而且它工作 然后你可以自己检查一个玩家是否还活着等等publicstaticvoidmain(字符串[]args){ //创建一些点。。。 List spawnPoints=new ArrayList(){{ 添加(新的繁殖点(0,0)); 添加(新的繁殖点(2,0)); 添加(新的繁殖点(0,5)); 增加(新的繁殖点(2,5)); }}; //创造一些球员 玩家playerA=新玩家(新位置(0,0)); 玩家B=新玩家(新位置(4,1)); Player playerC=新玩家((位置)空); //空位置表示玩家已死亡。 //将玩家添加到玩家列表中。。。 列表玩家=新的ArrayList(){{ 添加(playerA); 添加(playerB); 添加(playerC); }}; //产卵玩家(目前已死亡,需要重生) //并返回OP定义的最佳繁殖点 繁殖点sp=playerC.spawn(繁殖点,玩家); //打印职位 System.out.println(sp.getPosition()); }
注意:正如Marco13已经指出的,确定一个繁殖点和任何玩家之间的最大最小值更符合逻辑。或者你可以做一个算法,试图将两者都考虑进去。正如评论中所提到的,要具体说明实际问题有点困难。寻找调试帮助的问题通常被认为是离题的 从目前为止提供的信息来看,很难清楚地推导出参与此计算的对象的“状态空间”。例如,
和getCanSpawn()
之间的关系。不清楚getlifes()>0
标志何时将设置为canSpawn
或true
,以及false
生存计数何时减少。问题中的代码也没有考虑到其他玩家已经被<强>占据的位置不应该被用作产卵位置。 因此,一般建议将算法分解为更易于测试和调试的较小部分。例如,查看原始代码:
最里面的部分可以被提取到一个类似public void SpawnPlayers() { for (Player spawnPlayer : players) { if (spawnPlayer.getCharacter().getCanSpawn()) { ... } } }
private void spawnPlayer(Player playerToSpawn) { System.out.println("Spawning "+playerToSpawn); ... }
这也使我们更容易理解(并在控制台上查看)某个玩家何时将要诞生,以及该玩家之后会发生什么(如进一步的private Point computePointWithLargestMinimumDistance( Iterable<? extends Point> points, Set<? extends Point> others) { ... }
语句所示) 现在,有两件事与计算新玩家的繁殖位置相关:System.out
- 仍然可以产卵的位置
- 其他玩家拥有的位置(因此不再可用于产卵)
在这里,您可以传递其他玩家的Set<Point> availableSpawnPoints = ...; Set<Point> positionsOfOtherPlayers = ...;
和availableSpawnPoints
位置 (顺便说一句:方法签名是最通用的形式。你也可以使用mo
Set<Point> availableSpawnPoints = ...; Set<Point> positionsOfOtherPlayers = ...;
private Point computePointWithLargestMinimumDistance( Iterable<? extends Point> points, Set<? extends Point> others) { ... }
import java.awt.Point; import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; public class PlayerSpawning { public static void main(String[] args) { PlayerSpawning p = new PlayerSpawning(); p.spawnPlayers(); } private List<Player> players; private PlayerMap map; PlayerSpawning() { map = new PlayerMap(); players = new ArrayList<Player>(); Player player0 = new Player("player0"); player0.getCharacter().setPosition(new Point(0,0)); player0.getCharacter().setCanSpawn(false); players.add(player0); Player player1 = new Player("player1"); player1.getCharacter().setCanSpawn(true); players.add(player1); } public void spawnPlayers() { for (Player player : players) { if (player.getCharacter().getCanSpawn()) { spawnPlayer(player); } } } private void spawnPlayer(Player playerToSpawn) { System.out.println("Spawning "+playerToSpawn); Set<Point> availableSpawnPoints = new LinkedHashSet<Point>(map.getSpawnPoints()); Set<Point> positionsOfOtherPlayers = new LinkedHashSet<Point>(); for (Player player : players) { if (player.getCharacter().getLives() <= 0) { continue; } if (player.getCharacter().getCanSpawn()) { continue; } Point position = player.getCharacter().getPosition(); System.out.println( "Have to consider that "+player+" is at "+position+ " - this position is no longer available for spawing!"); positionsOfOtherPlayers.add(position); availableSpawnPoints.remove(position); } Point spawnPoint = computePointWithLargestMinimumDistance( availableSpawnPoints, positionsOfOtherPlayers); System.out.println("Spawning "+playerToSpawn+" at "+spawnPoint); playerToSpawn.getCharacter().spawn(spawnPoint); } private Point computePointWithLargestMinimumDistance( Iterable<? extends Point> points, Set<? extends Point> others) { System.out.println("Compute point from "+points); System.out.println("that is furthest from "+others); double largestMinDistance = Double.NEGATIVE_INFINITY; Point result = null; for (Point point : points) { double minDistance = computeMinimumDistance(point, others); if (minDistance > largestMinDistance) { largestMinDistance = minDistance; result = point; } } System.out.println( "The point that has the largest minimum " + "distance "+largestMinDistance+" to any other point is "+result); return result; } private double computeMinimumDistance( Point point, Iterable<? extends Point> others) { double minDistanceSquared = Double.POSITIVE_INFINITY; for (Point other : others) { minDistanceSquared = Math.min(minDistanceSquared, point.distanceSq(other)); } return Math.sqrt(minDistanceSquared); } } class Player { private String name; private Character character = new Character(); public Player(String name) { this.name = name; } public Character getCharacter() { return character; } @Override public String toString() { return name; } } class Character { private Point position = new Point(); private boolean canSpawn = false; public boolean getCanSpawn() { return canSpawn; } public void setCanSpawn(boolean canSpawn) { this.canSpawn = canSpawn; } public int getLives() { return 1; } public Point getPosition() { return position; } public void setPosition(Point p) { position.setLocation(p); } public void spawn(Point spawnPoint) { setPosition(spawnPoint); canSpawn = false; } } class PlayerMap { public List<Point> getSpawnPoints() { return Arrays.asList( new Point(0,0), new Point(200,0), new Point(0, 500), new Point(200,500)); } }
Spawning player1 Have to consider that player0 is at java.awt.Point[x=0,y=0] - this position is no longer available for spawing! Compute point from [java.awt.Point[x=200,y=0], java.awt.Point[x=0,y=500], java.awt.Point[x=200,y=500]] that is furthest from [java.awt.Point[x=0,y=0]] The point that has the largest minimum distance 538.5164807134504 to any other point is java.awt.Point[x=200,y=500] Spawning player1 at java.awt.Point[x=200,y=500]