代码之家  ›  专栏  ›  技术社区  ›  Relequestual

在sim游戏中生成和终止一个人(Java)

  •  4
  • Relequestual  · 技术社区  · 16 年前

    我正在开发一个基于2D网格的sim游戏。进步是好的。 在过去的几天里,我一直在破解代码,我今天遇到了一些问题。

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

    现在的问题是,如何处理“人”(其本身就是一个对象)已经完成了?我是否应该简单地设置一个布尔值,使它们不再处于“活动”状态,但其上的数据仍然存在?我不确定,所以我试着把它们从人们的ArrayList对象中删除。

    当这个人要被移除时,他们是,我检查arraylist的大小,然后我得到以下错误。。。线程“AWT-EventQueue-0”java.util.ConcurrentModificationException中出现异常

    有什么想法吗?思想?建议?对此有何评论?

    提前谢谢!

    (我将很快发布一段视频,并通过链接更新此问题)

    3 回复  |  直到 16 年前
        1
  •  3
  •   Eli    16 年前

    通常,我会给每个人、实体或任何东西一个称为isMarkedForDeletion的布尔字段。然后在主循环期间,它们要么被告知更新(),要么被标记为删除,它们的索引将被删除 . 填充完删除列表后,可以遍历删除列表并从主列表中删除这些对象。或者,您可以向后迭代,并从列表的末尾提取。

    这也许可以解释你的ConcurrentModificationException,也可能无法解释——我以前在使用ArrayList的时候从未得到过它们。然而,我从LinkedList那里得到了它们,这正是你描述的原因,与线程无关。实际原因是使用了迭代器。

    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();
        }
    }
    
        2
  •  1
  •   Zed    16 年前

    由于缺少任何代码摘录,这只是一个猜测,但很可能您的渲染是在Swing线程上的ArrayList中进行迭代,而另一个线程(我猜是计时器?)试图从列表中删除此人。

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

    // peopleArray and personInstance should be final
    Runnable removePersonTask = new Runnable() {
         public void run() {
             peopleArray.remove(personInstance).
         }
     };
    
    SwingUtilities.invokeLater(removePersonTask).
    
        3
  •  0
  •   Thomas Owens    16 年前

    出现此问题的一个常见原因是无法修改 ArrayList 当您在它上面迭代时。

    另外,因为您有一个GUI,所以您至少有两个线程。Swing和AWT在单独的线程上运行。因此,如果GUI直接访问 ArrayList ,可能有一些问题。