dan boy
dan boy

Reputation: 89

Detecting closest element in array

I'm having issues detecting the closest element in an array of blocks to the player (using circles).

What I have so far is:

public static int closestBarrier(GameObject object, GameObject[] barriers) {
    int closest = -1;
    float minDistSq = Float.MAX_VALUE;// ridiculously large value to start
    for (int i = 0; i < barriers.length; i++) {

        float barrierRadius = barriers[i].getWidth() / 2;
        float objectRadius = object.getWidth() / 2;

        GameObject curr = barriers[i];// current
        float dx = (object.getX()) - ((curr.getX()));
        float dy = (object.getY()) - ((curr.getY()));
        float distSq = (((dx * dx + dy * dy) - objectRadius) - barrierRadius)  ;// use the squared distance
        if (distSq < minDistSq) {// find the smallest and remember the id
            minDistSq = distSq;
            closest = i;
        }
    }

    return closest;
}

It passes most of the tests but on the final one the returned index of the closest one is 2 instead of the expected 3. Here are the tests (it is failing 'closest to fourth' :

    public final void testClosestBarrier() {
    // Closest to first
    GameObject player = new GameObject(0,1);
    player.setWidth(2);
    GameObject[] barriers = new GameObject[4];
    barriers[0] = new GameObject(8,9);
    barriers[0].setWidth(3);
    barriers[1] = new GameObject(10,15);
    barriers[1].setWidth(2);
    barriers[2] = new GameObject(15,20);
    barriers[2].setWidth(5);
    barriers[3] = new GameObject(100,210);
    barriers[3].setWidth(10);
    assertEquals("Player closest to first barrier",0,
            Submission.closestBarrier(player,barriers));

    // Closest to second
    player.setX(12);
    player.setY(12);
    assertEquals("Player closest to second barrier",1,
            Submission.closestBarrier(player,barriers));

    // Closest to third
    player.setX(12);
    player.setY(20);
    assertEquals("Player closest to third barrier",2,
            Submission.closestBarrier(player,barriers));

    // Closest to fourth
    player.setX(90);
    player.setY(100);
    assertEquals("Player closest to fourth barrier",3,
            Submission.closestBarrier(player,barriers));

}

Upvotes: 2

Views: 135

Answers (1)

Patashu
Patashu

Reputation: 21773

Your code is correct and the test you have written is wrong - barrier 2 is closer to 90,100 than barrier 3.

barrier 2:

(90-15)^2 + (100-20)^2

12025

barrier 3:

(100-90)^2 + (210-100)^2

12200

12025 < 12200 -> barrier 2 is closer

EDIT: In your edited answer, you forgot to square objectRadius and barrierRadius. e.g.

float distSq = (((dx * dx + dy * dy) - objectRadius) - barrierRadius)

In this line, you have dx^2, dy^2 but only non-squared objectRadius and barrierRadius.

Upvotes: 1

Related Questions