简体   繁体   中英

Java IndexOutOfBoundsException

I made an little shoot em up game..It works normal but I want also implement if fires intersects they will disappear. I have two list for Player bullets and for computer bullets ...But if I have more bullets from computer or reverse .Here my loop

     for (int i = 0; i < cb.size(); i++) {
        for (int j = 0; j < b.size(); j++) {
            if (b.get(j).rect.intersects(cb.get(i).rect)) {

                cb.remove(i);
                b.remove(j);


                continue;

            }
            if (cb.get(i).rect.intersects(b.get(j).rect)) {


                b.remove(j);
                cb.remove(i);

                continue;

            }

        }

    }

This is my game which woking algoritms... http://rapidshare.com/files/364597095/ShooterGame.2.6.0.jar

I highly recommend against playing with the for loop counters from within the loop itself. You are careful now, you won't be careful later ("let's try a hack here to debug") and end up with bugs.

One solution could be:

  • check whether two objects intersect
  • if they do, save a reference into a separate list of thingsToRemove
  • finally, go through the thingsToRemove and remove (or set to 'null', or -1 or whatever) the corresponding elements in the cb and b lists

As stated in Carl's comment the second if should be redundant.

As for your IndexOutOfBounds exception, this is caused by the following: When a computer bullet hits a player bullet, you remove both from the lists. Using continue you then continue comparing the same computer bullet to the remaining player bullets. However, that computer bullet was already removed before! Hence, I suggest you break instead of continue , then the next computer bullet is checked for intersection with player bullets.

As Roman hints at with his code you should further decrease the outer loop's counter, as you reduced the list size by removing one of the bullets. Hence, what used to be bullet #3 is in the next iteration what previously was bullet #4. So after the break you don't want the increment of the outer loop's counter.

the simplest modification to avoid logical error:

for (int i = 0; i < cb.size(); i++) {
    for (int j = 0; j < b.size(); j++) {
        if (b.get(j).rect.intersects(cb.get(i).rect)) {
            cb.remove(i--);
            b.remove(j--);
        }
    }
}

Running the loops backward should also do the trick:

for (int i = cb.size() - 1; i >= 0; i--) {
       for (int j = b.size() - 1; j >= 0; j--) {

EDIT: This solution can also encounter OOBE's. There are some unhandled cases... so I must recommend one of the higher-ranked solutions rather than this.

The problem with your code is that you are changing the size of list cb whenever you find an intersection, but then continue using the same index. For example, if cb has 3 elements and b has 4, and the 3rd (index = 2) computer bullet intersects the first player bullet, the size of cb is reduced to 2. When you then go on to check the second player bullet against the third computer bullet, there are only two items left in cb, and the game crashes.

In short, looping over lists and modifying them at the same time is difficult.

The other thing to consider is that if, for example, a computer bullet intersects with two player bullets, all three of them should be deleted. But if the computer bullet is deleted when it encounters the first player bullet, the second player bullet will remain.

In fact, there could be chains of bullets all touching one another, so deleting anything from the list before you've done all the intersections can lead to wrong results.

After a hilariously long time spent thinking about this, here's what I'd do. It ensures that everything that needs removing is removed and doesn't rely on index-munging.

ArrayList<Bullet> newB = new ArrayList<Bullet>(b);
ArrayList<Bullet> newCB = new ArrayList<Bullet>(cb);
for (Bullet pBullet : b) {
    for (Bullet cBullet : cb) {
        if (pBullet.rect.intersects(cBullet.rect)) {
            newB.remove(pBullet);
            newCB.remove(cBullet);
        }
    }
}
cb = newCB;
b = newB;

n my opinin, you can write in this way

   for (int i = cb.size() -1; i >= 0 ; i--) {
            boolean bremoved = false;
        for (int j = b.size() -1 ; j >=0 ; j--) {
            if (b.get(j).rect.intersects(cb.get(i).rect) ||
                cb.get(i).rect.intersects(b.get(j).rect)) {
                  bremoved = true;
                b.remove(j);
            }
        }
        if(bremoved)
            cb.remove(i);
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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