4

私は2Dグリッドベースのシムゲームを開発しています。進捗は良好です。過去数日間、コードを非常にうまく解読してきましたが、今日はいくつかの問題が発生しています。

部屋を2つ作り、ドアの位置を設定して、人をスポーンします。その人は、治癒するために訪問しなければならない2つの部屋タイプを持っています(これはテーマホスピタルのリメイクです)。スポーンボタンをクリックすると、Personは画面外からグリッドに移動し、スポーンが終了すると、最初の部屋への最初のパス、次に2番目のパス、そして最後のスポーンポイントに戻ります。

スポーンポイントとは、画面外/グリッド外のポイントを意味し、スポーン終了ポイントとは、スポーンサイクルが終了したときに人がいるポイントを意味し、完全に画面/グリッド上にあります。

問題は、「人」(それ自体がオブジェクトである)をどうするかということです。ブール値を単純に設定して、「アクティブ」ではなく、データが残るようにする必要がありますか?よくわからなかったので、保持されていた人々のオブジェクトのArrayListからそれらを削除しようとしました。

これを行うには、作成時に各人にArrayListの新しい位置と同じ数値を割り当て、削除するときにその番号を使用します。それ自体が床になっていることは知っていますが、現在テストしているのは1人だけです。誰かが私にそれについていくつかの助けを与えることができれば、素晴らしいです!しかし、それはもっとサブな質問だと思います。

その人が削除されるとき、彼らは削除され、配列リストのサイズを確認すると、次のエラーが発生します...「スレッド「AWT-EventQueue-0」の例外java.util.ConcurrentModificationException」

調査を行ったところ、これは異なるスレッドのオブジェクトの同期に関係していることは理解していますが、複数のスレッドがあるかどうかはわかりません。私はタイマーを1つ持っていますが、他の場所でArrayListにアクセスすることはないと思います。

何かご意見は?アイデア?提案?これについてのコメント?

前もって感謝します!

(私はすぐにビデオを投稿し、それへのリンクでこの質問を更新します)

4

3 に答える 3

3

通常、私はすべての人やエンティティ、またはisMarkedForDeletionと呼ばれるブールフィールドを指定します。次に、メインループ中に、update()するように指示されるか、削除のマークが付けられている場合は、インデックスが削除リストに追加されます。削除リストをすべて入力したら、削除リストを繰り返し処理して、それらのオブジェクトをメインリストから削除できます。または、逆方向に繰り返して、リストの最後からプルすることもできます。

これはあなたのConcurrentModificationExceptionを説明するかもしれないし、説明しないかもしれません-私は以前にArrayListを使って作業したときにそれらを取得したことがありません。しかし、私はLinkedListからそれらを取得しました。それはまさにあなたが説明した理由であり、スレッドとは何の関係もありませんでした。実際の原因はイテレータの使用でした。次の場合、ConcurrentModificationExceptionが発生します。

for (Iterator i = list.iterator(); i.hasNext();)
{
    Person o = i.next();

    o.update();

    if (list.isMarkedForDeletion())
    {
        list.remove(o);
    }
}

これにより、例外は発生しません。

ArrayList deletedObjects = new ArrayList();
for (Iterator i = list.iterator(); i.hasNext();)
{
    Person o = i.next();

    o.update();

    if (list.isMarkedForDeletion())
    {
        deletedObjects.add(o);
    }
}

for (int i = 0; i < deletedObjects.size(); i++)
{
    list.remove(deletedObjects.get(i));
}

おそらくそれを行う最も簡単な方法は、例外を引き起こしません

for (int i = list.size()-1; i >= 0; i--)
{
    Person o = list.get(i);

    if (o.isMarkedForDeletion())
    {
        list.remove(i);
    }
    else
    {
        o.update();
    }
}
于 2009-08-18T21:37:14.830 に答える
1

コードの抜粋がないため、大げさな推測ですが、おそらくあなたのレンダリングはSwingのスレッドのArrayListを反復処理しているのに対し、別のスレッド(私が推測するタイマー?)はリストからその人を削除しようとします。

その場合、1つの方法は、Swingにリストからその人物を(2つのレンダリングの間で)削除させることです。

// peopleArray and personInstance should be final
Runnable removePersonTask = new Runnable() {
     public void run() {
         peopleArray.remove(personInstance).
     }
 };

SwingUtilities.invokeLater(removePersonTask).
于 2009-08-18T16:43:48.620 に答える
0

この問題のより一般的な理由の1つは、ArrayList繰り返し処理している間は変更できないためです。

また、GUIがあるため、少なくとも2つのスレッドがあります。SwingとAWTは別々のスレッドで実行されます。したがって、GUIがに直接アクセスしている場合はArrayList、そこにいくつかの問題がある可能性があります。

しかし、コードがなければ、問題が何であるか、または何であるかを確実に知ることはできません。

于 2009-08-18T16:36:42.440 に答える