在删除和插入的同时通过for循环

时间:2011-10-25 14:40:23

标签: algorithm logic simulation

我正在编写捕食者/猎物模拟,其中物体可以出生或被杀死。当被杀死时,它们会从arraylist中删除,当它们出生时会被添加。列表中的每个对象都可以杀死另一个对象或复制。我浏览列表,模拟每个物体的运动以及与周围环境的相互作用,包括决定复制或杀死另一个物体(如果它关闭)。

循环中断的正常情况,就好像当前正在进行的索引发生删除或生成一样。 什么是更好的解决方案?用计数器和条件表示大小> 0或其他一些方式?

3 个答案:

答案 0 :(得分:5)

您可以等到迭代完成后添加/删除项目:

entities_to_add = new Array;
entities_to_remove = new Array;

function tick():
    for each entity in world:
        //general entity behavior goes here
        if entity.wants_to_reproduce:
            entities_to_add.append(entity.make_baby())
        if entity.wants_to_die:
            entities_to_remove.append(entity)

function cleanup():
    for each entity in entities_to_remove:
        world.remove(entity)
    for each entity in entities_to_add:
        world.add(entity)
    entities_to_remove.clear()
    entities_to_add.clear()

function main():
    while(True):
        tick()
        cleanup()

这有一个缺点,即死亡的实体看起来会一直存在,直到滴答结束。这可能是坏的,例如,如果捕食者杀死猎物,并且第二捕食者也在同一滴答中杀死该猎物。如果这是不可取的,你可以让掠夺者在攻击之前检查entities_to_remove数组,以确保它们的猎物仍然存活。

答案 1 :(得分:1)

在模拟中通常有两个世界副本 - 一个用于时间 t 的状态,一个用于时间 t +Δt的状态。

如果您没有两个副本,并在处理状态转换时尝试生成实体,那么列表中的第一个实体将看到与上一个不同的世界。

例如,如果更多的猎物出生而不是在蜱虫中砍伐,那么恰好位于列表末尾的掠食者将具有一个优势,这个优势不是被模拟的世界的一部分,而是你实施的人工制品。如果你已经添加了“红猫”和“蓝猫”,那么蓝猫会做得更好,没有任何真正的区别。

如果你确实有两个副本,那么你必须解决一个以上捕食者砍伐同一个猎物的问题,但你的原始问题将不存在。

答案 2 :(得分:0)

    ArrayList<Object> predators = new ArrayList<Object>();
    ArrayList<Object> preys = new ArrayList<Object>();
    for (Object predator : predators) {
      Object[] entities = preys.toArray();
      for (Object entity : entities) {
        if (entity.shouldReprodue()) {
            world.add(entity.baby());
        }
        if (entity.shouldDie()) {
            world.remove(entity);
        }
      }
    }

我认为每个捕食者都应该制作当前世界ArrayList的新副本。

相关问题