2015-04-07 2 views
0

Я делаю 2D-java-игру, основанную на Space Invaders. В моем классе Game У меня есть эти 3 поля:Ошибка Java-игры при обнаружении столкновений с LinkedList

//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 списке и проверьте столкновения с каждым Missilemissiles в списке, но он бросает 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) 

Игра проходит гладко, пока не произойдет столкновение. Пожалуйста, помогите мне!

+2

Смотреть это вопрос об [избегая ConcurrentModificationException] (http: // stackoverflow.com/questions/223918/iterating-through-a-list-avoiding-concurrentmodificationexception-when-remove) для обсуждения ** почему ** это происходит, а также некоторые варианты решения этой проблемы. –

ответ

5

Вы можете использовать remove() метод ListIterator в.

Использование ниже кода вместо 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(); 
    } 
} 
+0

спасибо, что работает отлично! Только один вопрос. Если можно сказать 'missiles.remove (m)' и 'iterMissiles.remove()', и они оба работают, почему невозможно удалить врагов через 'enemyLeft.remove (e)'? – Loupi

+0

Вы можете сослаться на [это] (http://stackoverflow.com/questions/223918/iterating-through-a-list-avoiding-concurrentmodificationexception-when-removing). 'Iterator.remove' является единственным безопасным способом изменения коллекции во время итерации. –

+0

Если вы хотите использовать 'missiles.remove (m)', то вам нужно выполнить шаги, указанные в ответе @Rawa –

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

Не может изменить список один итерация над:

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

должно быть:

iterEnimies.remove(); 
enemiesKilled.add(e); 
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 переменной и после того, как во время цикла удаления этого missilesForRemove из исходного missiles списка:

missiles.removeAll(missilesForRemove); 
Смежные вопросы