繁体   English   中英

数组索引超出范围

[英]Array index out of bounds

我不知道我缺少什么...完整的代码很大,所以我只在这里抛出异常。

      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子弹与外星人碰撞线上抛出了异常。 我添加了player.getBullets().get(i)getAliens()来确定哪一个抛出了异常,而那是玩家。

错误似乎是随机的,但是我相信当外星人向侧面移动到子弹上时,错误会超出范围。 如果子弹直接击中外星人,它会很好地工作。 使用相交会不会出错?

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

使用支持在其集合上进行remove操作的Iterator 给您一个想法(删除了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的影响。

在遍历列表时,您正在更改它们(通过在循环内调用.remove() )。 您将在检查与项目符号之间的冲突时删除项目符号。

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

问题是您要从遍历的数组中删除项目。 根据Javadoc:

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

这将产生一个数字,当您从集合中删除项目时,该数字将大于实际集合的大小,从而导致超出范围。

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

您应该创建迭代器来迭代玩家和外星人。 然后,当应该删除它时,请在迭代器而不是原始列表上执行此操作。 这使得循环工作。

正如@Toomai所建议的那样,与其删除而不是将其标记为死,也可以稍后将其删除,这也是一个不错的解决方案。

假设玩家0被杀死。 当您删除他的子弹时,所有其他子弹会在索引中向下移动一个。 因此,当索引增加到1时,您将看到的是最初的项目符号2,而不是项目符号1。

从索引列表中删除时,请始终以相反的顺序遍历循环,这样就不会影响要查看的元素的顺序。

但是,如果最后一颗子弹杀死了任何东西,您会看到(木棉)问题。 当您仍在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);

在您的代码中,您正在从列表中删除项目

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

可能发生的情况是,当外部循环的条件无效时,您仍在内部循环中循环。

在我看来,player.getBullets()。remove(i); 删除一些东西,但您继续循环。 您必须在System.out.println ...之后打破内部for循环。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM