Проблема со сравнением и TreeSet - PullRequest
1 голос
/ 09 мая 2011

У меня проблема с удалением юнитов TreeSets из игры, над которой я работаю.Я делаю игру Tower Defense, и путь разбит на разные блоки заданной длины.Блоки знают единицы в нем и следующий блок на пути.Когда юнит покидает границы блока, блок удаляет его из своего списка и добавляет в следующий блок.

Я использую TreeSet для отслеживания порядка юнитов в блоке,таким образом, я могу сказать, какой из них самый дальний по пути.У юнитов есть поле позиции, которое отслеживает, как далеко они проходят по пути, чем выше позиция, тем дальше они находятся.

На некоторых из моих блоков я заметил, что когда он пытается удалить юнитиз своего TreeSet удаление возвращает false.Я использовал некоторые точки останова, и я вижу, что модуль на самом деле находится в TreeSet, поэтому я думаю, что моя проблема - это метод сравнения для моих атакующих единиц.

Вот мой код для сравнения:*

Один из блоков, где я заметил проблему, это блок, в котором юниты входят в верхнюю часть, проходят половину угла и выходят с правой стороны.Блок имеет два ArrayList, один для юнитов, идущих сверху вниз (enPath) и один для юнитов слева направо (exPath).Вот код, в котором у меня проблема:

for (int i = 0; i < exPath.size(); i++) {
    AttackingUnit unit = exPath.get(i);
    unit.stepX();
    if (unit.getX() > rightX) {
        nextBlock.addUnit(unit);
        units.remove(unit);
        exPath.remove(unit);
        i--;
    }
}

Единица в exPath и в единицах (TreeSet), но unit.remove (unit) возвращает false.Любые идеи о том, как я могу изменить сравнить с AttackingUnit, чтобы исправить это?

Ответы [ 2 ]

1 голос
/ 09 мая 2011

Ваш метод сравнения является странным. Во-первых, в вашем списке не должно быть элементов неправильного типа, а также нулевых элементов, так как это все равно создаст проблемы. Таким образом, вы можете просто генерировать исключения в этих случаях вместо того, чтобы возвращать 1.

Во-вторых, как уже заметил Стив, проверка this == o неверна - это нарушает симметрию ваших отношений, давая вам случаи, когда ваши элементы не найдены. Это дает эту более простую версию:

public int compareTo(Object other) {
    AttackingUnit o = (AttackingUnit) other;
    int amount = position - o.position;
    return amount;
}

В-третьих, убедитесь, что позиции (то есть результаты ваших сравнений) не меняются, пока юнит находится в вашем TreeSet. Если позиции должны измениться, сначала удалите элемент из набора, измените позицию, а затем добавьте его снова.

1 голос
/ 09 мая 2011

Одна проблема, которую я вижу в вашем compareTo:

} else if (amount == 0 && this == o) {

Вы должны ИЛИ их (или избавиться от проверки this == o).Как и сейчас, два разных экземпляра AttackingUnit с одинаковым position вернутся как 1 (первый больше).Это определенно даст непоследовательный порядок в древовидном наборе.

Кстати, вы можете заменить:

if (other != null && AttackingUnit.class.isAssignableFrom(other.getClass()))

на

if (other instanceof AttackingUnit)

, который легче читать.

...