1

TreeSetsが作業中のゲームからユニットを削除する際に問題が発生しました。タワーディフェンスゲームを作っていますが、パスは設定された長さのさまざまなブロックに分割されています。ブロックは、その中のユニットとパス上の次のブロックを認識しています。ユニットがブロックの境界を離れると、ブロックはそのユニットをリストから削除し、次のブロックに追加します。

私はTreeSetを使用して、ブロック内のユニットの順序を追跡しています。これにより、パスに沿って最も遠いユニットを特定できます。ユニットには、パスに沿ってどれだけ離れているかを追跡する位置フィールドがあり、位置が高いほど遠くになります。

一部のブロックで、TreeSetからユニットを削除しようとすると、removeがfalseを返すことに気付きました。いくつかのブレークポイントを使用しましたが、ユニットが実際にTreeSetにあることがわかります。したがって、問題は攻撃ユニットのcompareToメソッドにあると思います。

これがcompareToの私のコードです:

public int compareTo(Object other) {
    if (other != null && AttackingUnit.class.isAssignableFrom(other.getClass())) {
        AttackingUnit o = (AttackingUnit) other;
        int amount = position - o.position;
        if (amount != 0) {
            return amount;
        } else if (amount == 0 && this == o) {
            return 0;
        }
    }
    return 1;
}

私が問題に気付いているブロックの1つは、ユニットが上部に入り、途中で角を曲がって右側から出るブロックです。ブロックには2つのArrayListがあります。1つは上から下に移動するユニット用(enPath)で、もう1つは左から右に移動するユニット用(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)にありますが、units.remove(unit)はfalseを返します。これを修正するためにAttackingUnitのcompareToを変更する方法に関するアイデアはありますか?

4

2 に答える 2

1

あなたの compareTo メソッドは奇妙です。まず、正しいタイプでない要素をリストに含めるべきではありません。また、null 要素も含めないでください。いずれにしても問題が発生するためです。したがって、これらのケースでは、を返す代わりに単純に例外をスローできます1

第二に、Steve がすでに述べたように、this == oチェックが正しくありません。これは関係の対称性に違反し、要素が見つからない場合をもたらします。これにより、この単純なバージョンが得られます。

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

第 3 に、ユニットが TreeSet 内にある間、位置 (つまり、比較の結果) が変わらないことを確認します。位置を変更する必要がある場合は、最初に要素をセットから削除し、位置を変更してから再度追加します。

于 2011-05-08T20:49:26.947 に答える