数组索引超出范围

时间:2011-11-30 19:15:42

标签: java arrays arraylist

我不知道我错过了什么......完整的代码非常大,所以我只是把这个部分放在这里抛出异常。

      for (int i = 0; i < player.getBullets().size(); i++) { //for every player bullet
            for (int j = 0; j < aliens.getAliens().size(); j++) { //for every player bullet every alien
                player.getBullets().get(i);
                aliens.getAliens().get(j);
                if (player.getBullets().get(i).getBounds().intersects(aliens.getAliens().get(j).getBounds())){ //player bullet vs alien collison
                    if (aliens.getAliens().get(j).getType() == 1)
                        score += 2 + level;
                    else if(aliens.getAliens().get(j).getType() == 2)
                        score += 4 + level;
                    else
                        score += 8 + level*2;
                    aliens.getAliens().remove(j); // alien dies
                    player.getBullets().remove(i);
                    System.out.println("player bullet removed");
                }
            }
        }       

它在//玩家子弹与外星人碰撞线上引发了异常。 我添加了player.getBullets().get(i)getAliens()来确定哪一个抛出了异常而且它是玩家一个。

错误似乎是随机的,但我相信当外星人侧身移动到子弹上时它会超出界限。如果子弹直接击中外星人,它可以正常工作。使用相交可能是错误吗?

顺便说一句,这是太空侵略者的模仿。任何帮助将不胜感激。

7 个答案:

答案 0 :(得分:3)

在其集合中使用支持Iterator操作的remove。为了给你一个想法(删除OP中所有不相关的代码):

    List<Bullet> bullets = new ArrayList<Bullet>();
    List<Alien> aliens = new ArrayList<Alien>();

    Iterator<Alien> alienIterator = aliens.iterator();
    Iterator<Bullet> bulletIterator = bullets.iterator();
    while (bulletIterator.hasNext()) { //for every player bullet
        while (alienIterator.hasNext()) { //for every player bullet every alien
            Bullet bullet = bulletIterator.next();
            Alien alien = alienIterator.next();
            if (bullet.getBounds().intersects(alien.getBounds())) { //player bullet vs alien collison
                bulletIterator.remove();
                alienIterator.remove();
                System.out.println("player bullet removed");
            }
        }
    }

请注意,如果您同时在其他地方修改外星人/子弹,它仍然容易受到IllegalStateException的影响。

答案 1 :(得分:2)

您正在遍历它们时改变列表(通过在循环内调用.remove())。您正在检查与其发生碰撞的过程中删除子弹。

一种解决方案是为外星人/子弹/其他此类物品提供isDead变量。然后,不要在循环内删除它们,而是等到循环之后,用isDead == true删除所有人。

答案 2 :(得分:1)

问题是您要从正在遍历的阵列中删除项目。根据Javadoc:

int size() 
Returns the number of elements in this collection.

这会产生一个数字,当你从集合中删除项目时,它会大于实际的集合大小,因此会导致超出界限。

您需要使用iterator遍历集合,然后在遍历集合时使用iterator.remove()从集合中删除项目。

答案 3 :(得分:1)

你应该创建迭代器来迭代玩家和外星人。然后,当应该删除一个迭代器而不是原始列表。这使循环工作。

正如@Toomai所建议的,不是删除,将它们标记为已死,可能会在以后删除它们,这也是一个不错的解决方案。

答案 4 :(得分:1)

让我们说玩家0被杀了。当你移除他的子弹时,所有其他子弹在索引中向下移动一个。因此,当索引增加到1时,您将查看最初的子弹2,而不是子弹1。

当按索引从List中删除时,总是以相反的顺序遍历循环,这样就不会影响仍然要查看的元素的顺序。

然而,如果最后一颗子弹杀死任何东西,你会看到(kapow)问题。当你仍然在for(j)循环中时,你删除了最后一颗子弹。对getBullet(i)的下一次调用将失败,因为不再有子弹i,现在只有i-1。当子弹杀死某些东西时,你应该突破内循环。 (假设子弹可以;一次杀死2个外星人)

那就是说,

你会得到更好的服务
  1. 使用新样式进行循环,for (Bullet bullet : player.getBullets() {}这将真正简化您的代码!!!
  2. 考虑不要动态删除。将要删除的所有内容收集到两个临时列表中,deadAliens和usedBullets。在循环调用结束时

    aliens.getAliens()。removeAll(deadAliens); player.getBullets()的removeAll(deadBullets);

答案 5 :(得分:0)

在您的代码中,您要删除我认为是列表的项目

 aliens.getAliens().remove(j); // alien dies
 player.getBullets().remove(i)

当外循环的条件无效时,可能会发生在内循环中的循环。

答案 6 :(得分:0)

向我看看player.getBullets()。remove(i);删除一些东西,但你继续循环。你必须在System.out.println ...

之后突破内部for循环