0

我知道这可能已经被问过很多次了,但是我有一个问题,我找不到特别针对我的问题的解决方案。

问题如下:

我有两个火箭和射弹的数组列表,并检查它们之间的碰撞。当它们碰撞时,它们都会被移除。问题是,当arraylist中唯一的火箭被击中时,就会发生异常,我不知道如何阻止它发生。

java.lang.IndexOutOfBoundsException: Index: 3, Size: 3
at java.util.ArrayList.rangeCheck(Unknown Source)
at java.util.ArrayList.get(Unknown Source)
at adam.miszczak.defendthebase.level.Level.collision(Level.java:158)
at adam.miszczak.defendthebase.level.Level.tick(Level.java:144)
at adam.miszczak.defendthebase.Game.tick(Game.java:124)
at adam.miszczak.defendthebase.Game.run(Game.java:104)
at java.lang.Thread.run(Unknown Source)

碰撞方法 + 数组列表:

public static ArrayList<Projectile> projectiles = new ArrayList<Projectile>();
private static ArrayList<Rocket> rockets = new ArrayList<Rocket>();

private void collision(){
    for(int i = 0; i < rockets.size(); i++){
        for(int j = 0; j < projectiles.size(); j++){
            try{
                if(rockets.get(i).bounds().intersects(projectiles.get(j).bounds())){
                    projectiles.remove(j);
                    rockets.get(i).die();
                    stats.addScore(rockets.get(i));
                    Particle p = new Particle(20, 20, 20, 50);
                    particles.add(p);
                }
            }catch(IndexOutOfBoundsException e){
                e.printStackTrace();
            }
        }
    }
}

删除和添加方法:

private void remove(ArrayList<Projectile> projectiles, ArrayList<Rocket> rockets){
    for(int i = 0; i < rockets.size(); i++){
        if(rockets.get(i).getVisible()){ rockets.remove(i); rocketsOnScreen--; }
    }

    for(int i = 0; i < projectiles.size(); i++){
        if(projectiles.get(i).isRemoved()){ projectiles.remove(i);}
    }

    for(int i = 0; i < planes.size(); i++){
        if(planes.get(i).isRemoved()){ planes.remove(i); planesOnLevel--;}
    }
}

private void spawnRocket(int rocketType, int x, ArrayList<Rocket> rockets) {
    switch (rocketType) {
        case ROCKET_NORMAL:
            rockets.add(new NormalRocket(x, -10, 80, 0, 2));
            rocketsSpawned++;
            rocketsOnScreen++;
            break;
        case ROCKET_FIRE:
            if(difficulty > 1 && random.nextInt(100) > fireRocketSpawn){
                    rockets.add(new FireRocket(x, -10, 70, 0, 2));
                    rocketsSpawned++;
                    rocketsOnScreen++;
            }else{
                return;
            }
            break;
        case ROCKET_ZIPPER:
            if(difficulty > 2 && random.nextInt(100) > zipperRocketSpawn){
                rockets.add(new ZipperRocket(x, -10, 40, 0, 4));
                rocketsSpawned++;
                rocketsOnScreen++;
            }else{
                return;
            }
            break;
        case ROCKET_TANK:
            if(difficulty > 3 && random.nextInt(100) > tankRocketSpawn){
                rockets.add(new TankRocket(x, -10, 130, 0, 1));
                rocketsSpawned++;
                rocketsOnScreen++;
            }else{
                return;
            }
            break;
    }
} 

注意:rocket.die() 基本上只是移除火箭,就像 remove 方法一样。

4

3 回答 3

1

在用 a以外的任何东西迭代 a时,您不能删除。想象一下后果;您正在遍历元素并删除元素。所有其他元素都向下移动一个以填补空白。你拿 element ,这是你开始循环时的元素。并且是一个更小的元素,因此您的边界检查现在是错误的。通过这种方式,您可以获得各种难以追踪的错误。ListIteratornn+1n+2List

在 Java 中,如果您使用正确的语法 - 即增强的 foreach 循环,那么如果您在迭代时尝试从列表中添加/删除,您将得到正确的错误 - 您将得到一个ConcurrentModificationException.

要修复您的方法,1)摆脱所有索引。你在滥用它们,它们是不必要的(现在很多次你在每次迭代中都从每个元素中得到相同的元素?)。List2) 使用实际Iterator的 for 内部循环,以便您可以调用Iterator.removeList. 因为这是通过Iterator它完成的,所以不会导致错误:

private void collision() {
    for (final Rocket rocket : rockets) {
        final Iterator<Projectile> iter = projectiles.iterator();
        while (iter.hasNext()) {
            final Projectile projectile = iter.next();
            if (rocket.bounds().intersects(projectile.bounds())) {
                rocket.die();
                stats.addScore(rocket);
                Particle p = new Particle(20, 20, 20, 50);
                particles.add(p);
                iter.remove();
            }
        }
    }
}
于 2013-10-05T21:37:35.037 回答
0

切勿在列表循环期间删除列表中的项目。它可能会产生并发问题。在循环之后立即标记要删除的数字。

不确定它是否会解决您的问题,但您肯定也应该解决它。

于 2013-10-05T21:29:13.010 回答
0

当检测到碰撞时,您调用

rockets.get(i).die();

你说,“死”将火箭从“阵列列表”中删除。然后你打电话

stats.addScore(rockets.get(i));

哪个会崩溃(这条线是158,不是吗?)

为简洁和格式道歉,我的手机第一次回答:-)

于 2013-10-05T21:39:00.323 回答