【问题标题】:Removing an entity and then adding a new one in its place删除一个实体,然后在其位置添加一个新实体
【发布时间】:2013-11-24 04:14:22
【问题描述】:

所以我正在制作一个僵尸模拟游戏。我所拥有的是一群玩家和僵尸在这一点上随机跑来​​跑去。当幸存者与僵尸相撞时,我希望它移除幸存者并用僵尸替换它,基本上将他变成僵尸。

碰撞检测工作正常(我只是使用带有 intersect 方法的 awt 矩形)。但是我有一个僵尸数组列表和一个幸存者数组列表。当发生碰撞时,我将僵尸添加到僵尸列表中。然后我从该列表中删除幸存者。它工作了几次,然后随机抛出一个索引越界异常。

java.lang.IndexOutOfBoundsException: Index: 13, Size: 13
    at java.util.ArrayList.rangeCheck(Unknown Source)
    at java.util.ArrayList.remove(Unknown Source)
    at com.caveragestudios.zombiesim.World.update(World.java:53)
    at com.caveragestudios.zombiesim.Main.update(Main.java:93)
    at com.caveragestudios.zombiesim.Main.run(Main.java:69)
    at java.lang.Thread.run(Unknown Source)

我尝试过使用高级 for 循环、常规 for 循环和带有 while 循环的迭代器。似乎没有任何工作。这是我现在的代码。

    for (int i = 0; i < survivors.size(); i++) {
        Survivor s = survivors.get(i);
        for (int ii = 0; ii < zombies.size(); ii++) {
            Zombie z = zombies.get(ii);
            if (z.bounds.intersects(s.bounds)) {
                zombies.add(new Zombie(s.position, this));
                survivors.remove(i);
            }
        }
    }

其他一切似乎都正常工作,只是当我尝试修改列表时它有点混乱并引发索引超出范围异常。有什么想法吗?

【问题讨论】:

    标签: java for-loop arraylist


    【解决方案1】:

    您已将外部列表survivors 索引i 用于内部列表zombies。您的索引变量在 zombies.get(i) 处有误。

      for (int i = 0; i < survivors.size(); i++) {
        Survivor s = survivors.get(i);
        for (int ii = 0; ii < zombies.size(); ii++) {
            Zombie z = zombies.get(ii);// Here use ii instead of i
          //..............
      }
     }
    

    要从集合中删除元素,请使用Iterator.remove。更改您的代码,如下所示,以便从集合中安全删除。

     Iterator<Survivor > survIt=survivors.iterator();     
     Iterator<Zombie> zombIt=zombies.iterator();
     while(survIt.hasNext()){
           Survivor s=survIt.next();    
    
             while(zombIt.hasNext()){
               Zombie  z=zombIt.next();
    
                if (z.bounds.intersects(s.bounds)) {
                zombies.add(new Zombie(s.position, this));
    
                survIt.remove(); //Use Iterator.remove.
    
                }                 
            }
      }
    

    【讨论】:

    • 哇,我不敢相信我错过了,哈哈。但是我已经改变了它,现在它不是工作几次然后打破,而是在第一次碰撞时打破。所以我认为这不是唯一的问题。
    • Darren,使用 Iterator.remove 从集合中移除元素。
    • 我不相信您可以使用它从列表中删除特定对象。我必须使用类似 while (survivors.iterator().hasNext()) 的东西。然后它就会卡在那里而不继续程序的其余部分。我试过了,我不相信它会起作用。
    • 这会引发 ConcurrentModificationException。经过研究,您无法在迭代列表时修改列表。我想我将不得不采取一种全新的方法来解决这个问题。
    【解决方案2】:

    好吧,我已经设法自己解决了这个问题。从马苏德向正确的方向推进。问题是我无法在迭代列表时修改列表,但是我仍然需要来自迭代器的数据。

    我所做的是创建两个新列表,一个名为 toRemove 以填充碰撞的幸存者。然后调用 toAdd 来填充碰撞的僵尸。

    然后像往常一样迭代,但不是直接从主列表中添加和删除,而是将它们添加到那些新列表中。然后在迭代完成后,相应地删除并添加这些新列表。这是最终代码。

        List<Survivor> toRemove = new ArrayList<Survivor>();
        List<Zombie> toAdd = new ArrayList<Zombie>();
    
        Iterator<Survivor> survIt = survivors.iterator();
        Iterator<Zombie> zombIt = zombies.iterator();
        while (survIt.hasNext()) {
            Survivor s = survIt.next();
            while (zombIt.hasNext()) {
                Zombie z = zombIt.next();
                if (z.bounds.intersects(s.bounds)){
                    toAdd.add(new Zombie(s.position, this));
                    toRemove.add(s);
                    System.out.println("collided");
                }
            }
        }
    
        for (Survivor s : toRemove) {
            survivors.remove(s);
        }
    
        for (Zombie z : toAdd) {
            zombies.add(z);
        }
    

    【讨论】:

      猜你喜欢
      • 2018-06-29
      • 1970-01-01
      • 2012-04-28
      • 1970-01-01
      • 1970-01-01
      • 2020-10-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多