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

时间:2015-04-07 10:39:41

标签: java multithreading linked-list concurrentmodification

我正在制作一个基于太空入侵者的2D java游戏。在我的Game课程中,我有以下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()方法中,我浏览了Enemy列表中的每个enemiesLeft,并检查了与Missile列表中每个missiles的冲突,但是抛出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)

游戏顺利进行,直到发生碰撞。 请帮帮我!

4 个答案:

答案 0 :(得分:5)

您可以使用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();
  }
}

答案 1 :(得分:0)

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

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

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

答案 2 :(得分:0)

有人可能不会改变正在迭代的列表:

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

应该是:

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

答案 3 :(得分:0)

问题出在这里:

 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循环中从原始missilesForRemove列表中删除此missiles

missiles.removeAll(missilesForRemove);