在模拟游戏中生成并终止一个人(Java 中)

发布于 2024-08-02 01:03:48 字数 866 浏览 5 评论 0原文

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

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

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

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

我通过在创建时为每个人分配一个数字值来做到这一点,该值与他们在 ArrayList 中的新位置相同,然后在删除它们时,使用该编号。 我知道这本身就令人困惑,但我现在只与 1 个人进行测试。 如果有人能给我一些帮助,那就太棒了! 但我认为这更多的是一个子问题。

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

我做了一些我正在研究,我知道这与不同线程中对象的同步有关,但我不确定我是否有多个线程。 我确实有一个计时器,而且我不认为在其他地方可以访问 people ArrayList。

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

提前致谢!

(我很快就会发布视频并更新此问题并附上链接)

I am developing a 2D grid based sim game. Progress is good.
Been cracking out code for the last few days really well, and I've been having some issues today.

I build two rooms, set the door position, and spawn a person. The person has the 2 room types that they must visit in order to be cured (It's a remake of Theme Hospital).
I click the spawn button, Person moves onto the grid from off screen, and then when the spawn is finished, they get their first path to the first room, then second, and then back to the ending spawn point.

When I say the spawn point, I mean the point off screen / off grid, when I say the ending spawn point, I mean the point where the person is when the spawn cycle is finished, and they are fully on screen / grid.

The problem now comes, what to do with the "person" (which is an object in its own right), is finished with? Should I simple set a boolean so they are no longer "active" but data on them remains? I wasn't sure, so I tried to just remove them from the ArrayList of people objects they were being held in.

I did this by assigning a number value to each person on creation which was the same as their new position in the ArrayList, and then when removing them, using that number. I know that in itself is floored, but I'm only testing with 1 person right now. If anyone can give me some help on that, fantastic! But I suppose that is more a sub question.

When the person is to be removed, they are, and I check the size of the arraylist, and then I get the following error... "Exception in thread "AWT-EventQueue-0" java.util.ConcurrentModificationException"

I did some researching and I understand this is to do with synchronisation of objects in different threads, but I'm not sure that I have more than one thread. I do have a single timer, and I don't think the people ArrayList is accessed elsewhere.

Any Thoughts? Ideas? Suggestions? Comments on this?

Thanks in advance!

(I will soon post a video and update this question with a link to it)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

夜光 2024-08-09 01:03:48

通常,我会给每个人或实体或任何东西一个名为 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();
    }
}

Typically I give every person or entity or whatever a boolean field called isMarkedForDeletion. Then during the main loop, they will either be told to update(), or if they are marked for deletion their index will be added to a deletion list. Once you have the deletion list all populated, you can iterate through the deletion list and remove those objects from the main list. Alternatively you can just iterate backwards and pull from the tail end of the list.

This may or may not explain your ConcurrentModificationException - I've never gotten them when working with ArrayList's before. However, I've gotten them from LinkedList's and it was precisely for the reason you described and had nothing to do with threads. The actual cause was using an Iterator. The following will cause a ConcurrentModificationException:

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

    o.update();

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

This will not cause an Exception:

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));
}

Perhaps the simplest way to do it, will not cause an Exception:

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

    if (o.isMarkedForDeletion())
    {
        list.remove(i);
    }
    else
    {
        o.update();
    }
}
倾城月光淡如水﹏ 2024-08-09 01:03:48

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

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

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

SwingUtilities.invokeLater(removePersonTask).

Just a wild guess due to the lack of any code excerpts, but most probably your rendering is iterating through the ArrayList on Swing's thread, while you another thread (the timer I guess?) tries to remove the person from the list.

If that's the case, one way to go is to have Swing remove the person from the list (between two renderings) as:

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

SwingUtilities.invokeLater(removePersonTask).
青萝楚歌 2024-08-09 01:03:48

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

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

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

One of the more common reasons for this problem is because you can not modify an ArrayList while you are iterating over it.

Also, since you have a GUI, you have at least two threads. Swing and AWT run on a separate thread. So if the GUI is directly accessing the ArrayList, there might be some problems there.

But without code, it's not possible to tell for sure what the problem is or might be.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文