2015-06-12 2 views
1

При программировании простой игры я пришел на исключение параллельной модификации, поэтому я посмотрел здесь и нашел два разных способа исправить это. Он работал, но, по неизвестным причинам, только тогда, когда игрок вызывает функцию, а не если AI игроки называют (ту же) функцию.[Java] Исправление одновременной модификации; Итератор не работает

версии 1.0 функции выглядит следующим образом:

public void eat(ArrayList<Enemy> enemys) { 
    ArrayList<Enemy> toRemove = new ArrayList<Enemy>(); 
    for(Enemy enemy : enemys) { 
     if(enemy.location.x != location.x && enemy.location.y != location.y) { //check for self 
      if(collidesWith(enemy)) { 
       if(width > enemy.width) { 
        width += enemy.width; 
        height = width; 
        toRemove.add(enemy); 
       } 
      } 
     } 
    } 

    enemys.removeAll(toRemove); 
} 

как это не сработало, я попробовал трюк с итератора, который, к сожалению, производит точно такую ​​же ошибку:

public void eat(ArrayList<Enemy> enemys) { 
    for(Iterator<Enemy> iterator = enemys.iterator(); iterator.hasNext();) { 
     Enemy enemy = iterator.next(); 
     if(enemy.location.x != location.x && enemy.location.y != location.y) { //check for self 
      if(collidesWith(enemy)) { 
       if(width > enemy.width) { 
        width += enemy.width; 
        height = width; 
        iterator.remove(); //remove the enemy 
       } 
      } 
     } 
    } 
} 

сообщение об ошибке:

Exception in thread "main" java.util.ConcurrentModificationException 
at java.util.ArrayList$Itr.checkForComodification(Unknown Source) 
at java.util.ArrayList$Itr.next(Unknown Source) 
at Main.runGame(Main.java:59) 
at Main.<init>(Main.java:43) 
at Main.main(Main.java:68) 

заранее спасибо

-v0xelDev

EDIT: в качестве Abishek Манохаран попросил runGame() метод, здесь это:

public void runGame() { 
    for(Enemy enemy : enemys) { 
     enemy.eat(enemys); 
     enemy.update(); 
    } 
    player.eat(enemys); 
    player.update(); 
} 
+0

Вы используете более одного потока? – assylias

+0

@assylias в настоящее время, нет – v0xelDev

+2

Как вы относите ошибку к методу 'eat()', но этот метод не отображается в вашей трассировке стека? –

ответ

1

Возможное исправление ...

public List eat(ArrayList<Enemy> enemys) { 
    ArrayList<Enemy> toRemove = new ArrayList<Enemy>(); 
    for(Enemy enemy : enemys) { 
     if(enemy.location.x != location.x && enemy.location.y != location.y) { //check for self 
      if(collidesWith(enemy)) { 
       if(width > enemy.width) { 
        width += enemy.width; 
        height = width; 
        toRemove.add(enemy); 
       } 
      } 
     } 
    } 

    return toRemove; 
} 

public void runGame() { 
    for(Enemy enemy : enemys) { 
     List eaten = enemy.eat(enemys); 
     enemy.update(); 
    } 
    enemys.removeAll(eaten); 
    player.eat(enemys); 
    player.update(); 
} 
0

Стек трассировки помещает местоположение исключения в строке 59 Main.java, в методе runGame(). Эта строка, по-видимому, является частью цикла, который выполняет итерацию над коллекцией, которая была изменена иначе, чем через контрольный Iterator. Если комментирование вызова eat() из этого цикла решает проблему, то должно быть, что аргумент, переданный этому методу, относится к той же коллекции, которая выполняется итерацией. Так что не делай этого.

Ваш второй код для eat() имеет лучшую форму, но он не затрагивает проблему, связанную с итерацией где-то дальше по дереву вызовов.

Как вы должны это исправить, это зависит от вашего поведения. В частности, если вы хотите избежать enemy s, которые есть от возможности есть других врагов (как ваш текущий код пытается сделать), тогда вам понадобится нечто более сложное. С другой стороны, если вы хотите каждый враг, чтобы получить свой шанс, даже если он сам ели в этом такте часов игры, то вы можете работать с копией enemys коллекции, может выглядеть примерно так:

public void runGame() { 
    List<Enemy> enemysCopy = new ArrayList<>(enemys); 

    for(Enemy enemy : enemys) { 
     enemy.eat(enemysCopy); 
    } 
    enemys.retainAll(enemysCopy); 
    player.eat(enemys); 
    player.update(); 
} 
1

Это проблема:

for(Enemy enemy : enemys) { 
    enemy.eat(enemys); 
    enemy.update(); 
} 

ешьте изменяет монстр вы перебор с для.

Смежные вопросы