Click here to Skip to main content
15,881,248 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hello,

I have an array of N players in Java. Each player has a position by (X,Y) coordinates.
I get as input a new player, with his position.

I have to find the K closest players in the array to the input player.
How can I do it in Java?

I thought about going thru the players array, and keep a K-size array with the current K closest players, and update it as I go thru the players array.
But for this, I must have a "distance to input player" comparator.
The problem is that the comparator compares between 2 objects, but now I need to compare which of the 2 players is closest to the input player.

1) How can I do it in Java?

2) Is there a better option to find the K closest players?

Thanks
Posted

Use a distance function D=sqrt((x1-x2)^2+(y1-y2)^2) and keep the closets ones on the array of K elements.
Depending on what your final problem is you could either compare with all and sort, then grab first K, or do it in one pass while putting new ones in a sorted list. up to you.

hope it helps.
 
Share this answer
 
Comments
user_code 17-Apr-12 12:28pm    
Thanks for your answer.

The problem with this solution, is that I have to keep the distance D in each player object.

Is there a solution without keeping the distance in the player object, and without creating a new class of playerID and distance?

Thanks
TorstenH. 18-Apr-12 4:21am    
why must the value Distance be a member of Player? That would be a complete Array of values, because you never know who asks.

calculate it on the fly when a Player asks.
Fredrik Bornander 18-Apr-12 4:39am    
I've updated my solution to cater for this requirement, I hope it solves your problem.
/Fredrik
If you have a Player class that looks something like this;

Java
package my.company;

public class Player {
    private final double x;
    private final double y;
    
    public Player(final double x, final double y) {
        this.x = x;
        this.y = y;
    }
    
    public double getX() { return x; }
    
    public double getY() { return y; }
    
    public double getDistance(final Player other) {
        final double dx = getX() - other.getX(); 
        final double dy = getY() - other.getY();
        
        return Math.sqrt(dx*dx + dy*dy);
    }
}


And a map class between holding a player and a distance to another (implicit) player that implements Comparable<Player>;

Java
package my.company;

public class PlayerDistance implements Comparable<playerdistance> {
    
    private final Player player;
    private final double distance;
    
    public PlayerDistance(final Player player, final double distance) {
        this.player = player;
        this.distance = distance;
    }
    
    public Player getPlayer() {
        return player;
    }
    
    public double getDistance() {
        return distance;
    }

    @Override
    public int compareTo(PlayerDistance other) {
        return distance < other.distance ? -1 : 1;
    }
}


The the list of K closest Players can be retrieved like this;

Java
package my.company;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Program {
    public static Iterable<playerdistance> getClosest(
          final Player source, 
          final Iterable<player> others, 
          int maxToGrab) {
        final List<playerdistance> distances = new ArrayList<playerdistance>();
        for(final Player player : others) {
            distances.add(new PlayerDistance(player, source.getDistance(player)));
        }
        
        Collections.sort(distances);
        return distances.subList(0, Math.min(maxToGrab, distances.size()));
    }

    public static void main(String[] args) throws Exception {
        final List<player> players = new ArrayList<player>();
        players.add(new Player(1.0, 1.0));
        players.add(new Player(2.0, 2.0));
        players.add(new Player(3.0, 3.0));
        
        final Player me = new Player(0.0, 0.0);
        for(final PlayerDistance playerDistance : getClosest(me, players, 2)) {
            System.out.println(playerDistance.getPlayer() +  " at " + playerDistance.getDistance());
        }
    }
}


Added:
The above solution gives the distances as well as the closest Players, but if as you say it's more important not to create another class then that can be achieved by letting Player implement Comparator (not Comparable).

Like, this;
Java
package my.company;

import java.util.Comparator;

public class Player implements Comparator<Player> {
    private final String name;
    private final double x;
    private final double y;
    
    public Player(final String name, final double x, final double y) {
        this.name = name;
        this.x = x;
        this.y = y;
    }
    
    public double getX() {
        return x;
    }
    
    public double getY() {
        return y;
    }
    
    @Override
    public String toString() {
        return name;
    }
    
    public double getDistance(final Player other) {
        final double dx = getX() - other.getX(); 
        final double dy = getY() - other.getY();
        
        return Math.sqrt(dx*dx + dy*dy);
    }

    @Override
    public int compare(Player o1, Player o2) {
        final double distanceDelta = getDistance(o1) - getDistance(o2); 
        return distanceDelta < 0 ? -1 : 1; 
    }
}


Then, the method of finding the K closest simply becomes;

Java
package my.company;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Program {

    public static Iterable<Player> getClosest(final Player source, final List<Player> others, int maxToGrab) {
        Collections.sort(others, source);
        return others.subList(0, Math.min(maxToGrab, others.size()));
    }

    public static void main(String[] args) throws Exception {

        final List<Player> players = new ArrayList<Player>();
        players.add(new Player("A", 1.0, 1.0));
        players.add(new Player("B", 2.0, 2.0));
        players.add(new Player("C", 3.0, 3.0));
        players.add(new Player("D", 1.0, 0.5));
        
        final Player me = new Player("S", 0.0, 0.0);
        
        for(final Player player : getClosest(me, players, 2)) {
            System.out.println(player);
        }
    }
}


Hope this helps,
Fredrik
 
Share this answer
 
v3
Comments
user_code 18-Apr-12 5:24am    
Thanks :)
TorstenH. 18-Apr-12 5:26am    
please accept both as both are correct.
user_code 18-Apr-12 5:28am    
Accepted
01234567890
00
01 a
02
03
04 x b
05
06 c

Player a
Player b
right angle x

a to x = 3
b to x = 4
a to b = 5
(3,4,5 triangle)

a*a = 9
b*b = 16


distance from a to b =
Math.sqrt((a*a) + (b*b))

distance from c to b =
b to x = 3
c to x = 2
(3*3)+(2*2)=13
Math.sqrt(13) = 3.605551275463989

x must be at right angles (90degrees) to both of other points
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900