Java 使用 LinkedList 进行碰撞检测时游戏崩溃

Java game crash on collision detection with LinkedList

我正在制作一款基于 Space Invaders 的 2D java 游戏。在我的游戏 class 中,我有这 3 个字段:

//enemies left to kill
private LinkedList<Enemy> enemiesLeft = new LinkedList<Enemy>(); 
//enemies killed
private LinkedList<Enemy> enemiesKilled = new LinkedList<Enemy>();
//missiles that have been fired
private LinkedList<Missile> missiles = new LinkedList<Missile>();

在我的 checkCollision() 方法中,我 运行 通过 enemiesLeft 列表中的每个 Enemy 并检查与 [=18] 中每个 Missile 的冲突=] 列表,但它会抛出 ConcurrentModificationException.

这里是 checkCollision() 方法:

private void checkCollisions(){
  //make an iterator over enemies
  ListIterator<Enemy> iterEnemies = enemiesLeft.listIterator();   

  //loop through enemies
  while(iterEnemies.hasNext()){
    //error is thrown at below line
    Enemy e = iterEnemies.next();  //current Enemy

    //go through each Missile
    ListIterator<Missile> iterMissiles = missiles.listIterator(); 
    while(iterMissiles.hasNext()){
      Missile m = iterMissiles.next();  //current Missile
      if(e.doesIntersect(m)){           
      //remove Enemy from enemiesLeft and add it to enemiesKilled list
      enemiesKilled.add(enemiesLeft.remove(enemiesLeft.indexOf(e)));
      //remove Missile
      missiles.remove(m);
      }
    }
  }
   updateScore();
}

这是我得到的错误:

java.util.ConcurrentModificationException
   at java.util.LinkedList$ListItr.checkForComodification(Unknown Source)
   at java.util.LinkedList$ListItr.next(Unknown Source)
   at Game.checkCollisions(Game.java:168)
   at Game.run(Game.java:197)
   at Game.main(Game.java:279)
   at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
   at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
   at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
   at java.lang.reflect.Method.invoke(Unknown Source)
   at      edu.rice.cs.drjava.model.compiler.JavacCompiler.runCommand(JavacCompiler.java:272)

在发生碰撞之前,游戏 运行 一直很流畅。 请帮助我!

问题出在迭代列表时修改了列表。如果要修改,则不允许在迭代时更改列表。

保存要删除的实例,然后在(伪代码)之后删除它们:

ArrayList<Item> ItemsToRemove = new ArrayList<Item>();

for(Item item : allItems){
  if(shouldItemBeRemoved(item)){
    ItemsToRemove.add(item)
  }
}

//Remove the items for the allItems list
for(Item item : itemToRemove){
  allItems.remove(item);
}

或使用迭代器删除项目:

iterMissiles.remove();

您可以使用 ListIterator 的 remove() 方法。

使用下面的代码代替 missiles.remove(m);

iterMissiles.remove();

enemiesLeft 中删除也是如此。

while(iterMissiles.hasNext()){
  Missile m = iterMissiles.next();  //current Missile
  if(e.doesIntersect(m)){           
  //remove Enemy from enemiesLeft and add it to enemiesKilled list
  enemiesKilled.add(e);
  iterEnemies.remove();

  //remove Missile
  iterMissiles.remove();
  }
}

不能更改正在迭代的列表:

enemiesKilled.add(enemiesLeft.remove(enemiesLeft.indexOf(e)));

应该是:

iterEnimies.remove();
enemiesKilled.add(e);

问题在这里:

 while(iterMissiles.hasNext()){
      Missile m = iterMissiles.next();  //current Missile
      if(e.doesIntersect(m)){           
      //remove Enemy from enemiesLeft and add it to enemiesKilled list
      enemiesKilled.add(enemiesLeft.remove(enemiesLeft.indexOf(e)));
      //remove Missile
      missiles.remove(m);
      }

您在遍历项目时尝试从 missiles 中删除项目。它抛出了 java.util.ConcurrentModificationException

在遍历 missiles 之前添加新列表:

LinkedList<Missile> missilesForRemove = new LinkedList<Missile>();

并添加到此列表 m 变量并在 while 循环后从原始 missiles 列表中删除此 missilesForRemove

missiles.removeAll(missilesForRemove);