[英]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名外星人)
也就是说,您会更好地为您服务
for (Bullet bullet : player.getBullets() {}
确实可以简化您的代码!!! 考虑不要即时删除。 将要删除的所有内容收集到两个临时列表中,即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.