4

我正在开发一个基于 2D 网格的模拟游戏。进步是好的。最近几天一直在很好地破解代码,今天我遇到了一些问题。

我建了两个房间,设置了门的位置,然后生成了一个人。此人有 2 种房间类型,他们必须访问才能治愈(这是主题医院的翻版)。我单击生成按钮,人物从屏幕外移到网格上,然后当生成完成时,他们将获得通往第一个房间的第一条路径,然后是第二条路径,然后返回到结束生成点。

当我说生成点时,我指的是屏幕外/网格外的点,当我说结束生成点时,我指的是当生成周期完成时人所在的点,并且他们完全在屏幕/网格上。

现在问题来了,“人”(它本身就是一个对象)怎么办?我是否应该简单地设置一个布尔值,以便它们不再“活动”但它们的数据仍然存在?我不确定,所以我试图将它们从他们所持有的人员对象的 ArrayList 中删除。

我通过在创建时为每个人分配一个与他们在 ArrayList 中的新位置相同的数字值来做到这一点,然后在删除它们时使用该数字。我知道这本身就是一个问题,但我现在只测试 1 个人。如果有人可以在这方面给我一些帮助,那就太好了!但我想这更像是一个子问题。

当这个人要被删除时,他们是,我检查了数组列表的大小,然后我得到以下错误......“线程中的异常“AWT-EventQueue-0”java.util.ConcurrentModificationException”

我做了一些研究,我知道这与不同线程中的对象同步有关,但我不确定我有多个线程。我确实有一个计时器,而且我认为不会在其他地方访问 people 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));
}

也许最简单的方法不会导致 Exception

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,而您的另一个线程(我猜是计时器?)试图从列表中删除该人。

如果是这种情况,一种方法是让 Swing 从列表中删除人员(在两个渲染之间),如下所示:

// 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

此问题的更常见原因之一是ArrayList您在迭代它时无法修改。

此外,由于您有一个 GUI,因此您至少有两个线程。Swing 和 AWT 在单独的线程上运行。因此,如果 GUI 直接访问ArrayList,那里可能会出现一些问题。

但是如果没有代码,就无法确定问题是什么或可能是什么。

于 2009-08-18T16:36:42.440 回答