Java IndexOutOfBoundsException

Я заставил мало стрелять в них игра.. Это работает нормальное, но я хочу также реализацию, если огни пересекутся, то они исчезнут. Я имею два, перечисляют для маркеров Плеера и для компьютерных маркеров... Но если я имею больше маркеров от компьютера или инвертирую.Here мой цикл

     for (int i = 0; i < cb.size(); i++) {
        for (int j = 0; j < b.size(); j++) {
            if (b.get(j).rect.intersects(cb.get(i).rect)) {

                cb.remove(i);
                b.remove(j);


                continue;

            }
            if (cb.get(i).rect.intersects(b.get(j).rect)) {


                b.remove(j);
                cb.remove(i);

                continue;

            }

        }

    }

Это - моя игра который алгоритмы Уокинга... http://rapidshare.com/files/364597095/ShooterGame.2.6.0.jar

5
задан Ercan 17 March 2010 в 15:41
поделиться

6 ответов

Я настоятельно рекомендую против играть со счетчиками цикла for из самого цикла. Вы осторожны сейчас, вы не будете осторожны позже («давайте попробуем взломать здесь для отладки») и в конечном итоге получите ошибки.

Одним из решений может быть:

  • проверить, пересекаются ли два объекта
  • , если они пересекаются, сохранить ссылку в отдельный список thingsToRemove
  • , наконец, пройти через thingsToRemove и удалите (или установите значение null, или -1 или что-то еще) соответствующие элементы в списках cb и b
7
ответ дан 18 December 2019 в 10:43
поделиться

Как указано в комментарии Карла, второе if должно быть лишним.

Что касается исключения IndexOutOfBounds, то оно вызвано следующим: Когда пуля компьютера попадает в пулю игрока, вы удаляете обе пули из списков. Затем, используя continue, вы продолжаете сравнивать ту же компьютерную пулю с оставшимися пулями игроков. Однако эта компьютерная пуля уже была удалена ранее! Поэтому я предлагаю вместо continue использовать break, тогда следующая компьютерная пуля будет проверяться на пересечение с пулями игроков.

Как намекает Роман в своем коде, вам следует еще уменьшить счетчик внешнего цикла, так как вы уменьшили размер списка, удалив одну из пуль. Следовательно, то, что раньше было пулей №3, на следующей итерации станет пулей №4. Поэтому после break вам не нужен инкремент счетчика внешнего цикла.

6
ответ дан 18 December 2019 в 10:43
поделиться

Проблема с вашим кодом заключается в том, что вы изменяете размер списка cb всякий раз, когда находите пересечение, но затем продолжаете использовать тот же индекс. Например, если cb имеет 3 элемента, а b - 4, а третья (индекс = 2) компьютерная пуля пересекает пулю первого игрока, размер cb уменьшается до 2. Когда вы затем продолжаете проверять пулю второго игрока на третья компьютерная пуля, в cb осталось только два предмета, и игра вылетает.

Короче говоря, перебирать списки и одновременно изменять их сложно.

Еще одна вещь, которую следует учитывать, это то, что если, например, компьютерная пуля пересекается с двумя пулями игрока, все три из них должны быть удалены. Но если компьютерная пуля будет удалена, когда она встретит пулю первого игрока, пуля второго игрока останется.

На самом деле, цепочки пуль могут касаться друг друга, поэтому удаление чего-либо из списка до того, как вы сделаете все пересечения, может привести к неверным результатам.

После забавно долгого размышления об этом, вот что я бы сделал. Это гарантирует, что все, что нужно удалить, будет удалено и не зависит от изменения индекса.

ArrayList<Bullet> newB = new ArrayList<Bullet>(b);
ArrayList<Bullet> newCB = new ArrayList<Bullet>(cb);
for (Bullet pBullet : b) {
    for (Bullet cBullet : cb) {
        if (pBullet.rect.intersects(cBullet.rect)) {
            newB.remove(pBullet);
            newCB.remove(cBullet);
        }
    }
}
cb = newCB;
b = newB;
1
ответ дан 18 December 2019 в 10:43
поделиться

По моему мнению, вы можете написать так

   for (int i = cb.size() -1; i >= 0 ; i--) {
            boolean bremoved = false;
        for (int j = b.size() -1 ; j >=0 ; j--) {
            if (b.get(j).rect.intersects(cb.get(i).rect) ||
                cb.get(i).rect.intersects(b.get(j).rect)) {
                  bremoved = true;
                b.remove(j);
            }
        }
        if(bremoved)
            cb.remove(i);
    }
0
ответ дан 18 December 2019 в 10:43
поделиться

the простейшая модификация, чтобы избежать логической ошибки:

for (int i = 0; i < cb.size(); i++) {
    for (int j = 0; j < b.size(); j++) {
        if (b.get(j).rect.intersects(cb.get(i).rect)) {
            cb.remove(i--);
            b.remove(j--);
        }
    }
}
1
ответ дан 18 December 2019 в 10:43
поделиться

Выполнение циклов в обратном направлении также должно помочь:

for (int i = cb.size() - 1; i >= 0; i--) {
       for (int j = b.size() - 1; j >= 0; j--) {

РЕДАКТИРОВАТЬ: Это решение также может вызывать OOBE. Есть несколько необработанных случаев ... поэтому я должен порекомендовать одно из решений с более высоким рейтингом, а не это.

1
ответ дан 18 December 2019 в 10:43
поделиться
Другие вопросы по тегам:

Похожие вопросы: