Java 数组索引超出范围
我不知道我错过了什么。。。完整的代码相当大,所以我将把抛出异常的部分放在这里Java 数组索引超出范围,java,arrays,arraylist,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
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");
}
}
}
for(int i=0;i
它在//玩家子弹与外星人的碰撞线上抛出了一个异常。
我添加了player.getbollets().get(I)
和get异形()
,以确定哪一个抛出了异常,而它是player
这个错误似乎是随机的,但我相信当一个外星人从侧面撞到一颗子弹上时,它就超出了范围。如果子弹直接击中外星人,效果很好。这可能是使用相交时的错误吗
顺便说一句,这是太空入侵者的模拟。任何帮助都将不胜感激。您在遍历列表时正在更改列表(通过在循环中调用
.remove()
)。在检查与它碰撞时,你正在删除子弹。
一种解决方案是给外星人/子弹/其他此类对象一个
isDead
变量。然后,不要在循环中删除它们,而是等到循环结束后再删除所有代码中带有isDead==true
的项,我猜这是从列表中删除项
aliens.getAliens().remove(j); // alien dies
player.getBullets().remove(i)
可能发生的情况是,当外部循环的条件无效时,您仍在内部循环中循环。问题是您正在从正在遍历的数组中删除项。根据Javadoc:
int size()
Returns the number of elements in this collection.
这将产生一个数字,当您从集合中移除项时,该数字将大于实际集合大小,从而导致越界
您需要使用遍历集合,然后在遍历集合时使用从集合中删除项。您应该创建迭代器来遍历玩家和外星人。然后,当应该删除一个时,在迭代器上而不是在原始列表上执行该操作。这使得循环有效
正如@Toomai所建议的,与其删除,不如将它们标记为死亡,以后可能删除它们,这也是一个很好的解决方案。在我看来,这名玩家。getBullets().remove(i);删除某些内容,但继续循环。必须在System.out.println…之后中断内部for循环,使用
迭代器
,它支持对其集合执行删除
操作。给你一个想法(从OP中删除所有不相关的代码):
列表项目符号=新建ArrayList();
列表=新的ArrayList();
迭代器alienIterator=外星人。迭代器();
迭代器bulletIterator=项目符号。迭代器();
而(bulletIterator.hasNext()){//
while(alienIterator.hasNext()){//对于每个玩家子弹每个外星人
Bullet=bulletIterator.next();
外星人=alienIterator.next();
如果(bullet.getBounds().与(alien.getBounds())相交{//player bullet vs alien collison
bulletIterator.remove();
alienIterator.remove();
System.out.println(“已移除播放器子弹”);
}
}
}
请注意,如果您同时在其他地方修改外星人/子弹,它仍然容易受到非法状态异常的影响。假设玩家0被杀。当你取出他的子弹时,所有其他的子弹在索引中向下移动一颗。因此,当索引增加到1时,您将看到最初的项目符号2,而不是项目符号1 按索引从列表中删除时,始终按相反顺序遍历循环,这样就不会影响仍要查看的元素的顺序 然而,如果最后一颗子弹杀死了任何东西,你就会看到问题(卡波)。当您仍在for(j)循环中时,删除最后一个项目符号。下一次调用getBullet(i)将失败,因为不再有bullet i,现在只有i-1。当一颗子弹杀死了什么东西时,你应该打破内环。(假设一颗子弹不能同时杀死两个外星人) 也就是说,你会得到更好的服务
for(Bullet-Bullet:player.getBullets(){}
它将真正简化您的代码请发布异常,或者至少告诉它发生在哪一行
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");
}
}
}