我知道之前可能已多次询问此问题,但我遇到了问题而且找不到特别针对我的问题的解决方案。
问题如下:
我有两个火箭和射弹的arraylists,并在它们之间检查碰撞。当它们发生碰撞时,它们都会被移除。问题是,当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)
碰撞方法+ arraylists:
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方法一样。
答案 0 :(得分:1)
在使用List
以外的任何内容迭代Iterator
时,您无法删除。想象一下后果;您正在遍历元素并删除元素n
。所有其他元素向下移动以填补空白。你从元素n+1
开始,现在从开始循环开始就是元素n+2
。并且List
是一个较小的元素,因此您的边界检查现在是错误的。你可以用这种方式获得各种难以追踪的错误。
在Java中,如果你使用正确的语法 - 即enhanced foreach loops,那么如果你在迭代时尝试添加/删除列表,你将得到正确的错误 - 你会得到一个{ {3}}
要修复你的方法,1)摆脱所有索引。你滥用它们并且它们是不必要的(现在很多次你在每次迭代中从每个List
得到相同的元素?)。 2)对内部循环使用实际ConcurrentModificationException
,以便您可以调用Iterator.remove
从List
中删除最后返回的元素。因为这是通过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();
}
}
}
}
答案 1 :(得分:0)
切勿在循环列表中删除列表中的项目。它可能会给出并发性问题。在循环后立即标记要删除的数字。
不确定它是否能解决你的问题,但是你也应该解决这个问题。
答案 2 :(得分:0)
当检测到碰撞时,请致电
rockets.get(i).die();
你说,stats.addScore(rockets.get(i));
会崩溃(此行是158,不是吗?)
为简洁和格式化而道歉,从我的手机给出第一个答案: - )