We closed this forum 18 June 2010. It has served us well since 2005 as the ALPHA forum did before it from 2002 to 2005. New discussions are ongoing at the new URL http://forum.processing.org. You'll need to sign up and get a new user account. We're sorry about that inconvenience, but we think it's better in the long run. The content on this forum will remain online.
IndexProgramming Questions & HelpPrograms › index out of bounds exception...not sure why
Page Index Toggle Pages: 1
index out of bounds exception...not sure why (Read 564 times)
index out of bounds exception...not sure why
Apr 7th, 2010, 2:42pm
 
so im getting an index out of bounds exception and im not sure why if any one can help that would be great. im trying to create a game like destruct-o-match from neopets where you click blocks and then they explode and disappear. heres my code:
Code:
int pointer = 0;
int pointer2 = 0;
int maxRow = 10;
int maxCol = 10;
int blocksize = 25;
PVector[] adjlocs = new PVector[maxCol*maxRow];
Block[][] blocksList = new Block[maxCol][maxRow];
ArrayList[] blocks = new ArrayList[maxCol];
PVector[] loclist = new PVector[maxCol*maxRow];

void setup(){
 size(960,600);
 /////////////populating blocks in blocks blocksList matrix
 for(int i = 0; i< maxCol;i++){
   blocks[i] = new ArrayList();
   for(int x = 0; x< maxRow;x++){
     blocksList[i][x] = new Block(width/2+i*25, height/2+x*25, blocksize, int(random(0,2)), true);
     blocks[i].add(new Block(width/2+i*25, height/2+x*25, blocksize, int(random(0,2)), true));
   }
 }
}

void draw(){
 background(0);
 for(int i=0;i<maxCol;i++){
   for(int x=0;x<blocks[i].size();x++){
     Block tempblock = (Block) blocks[i].get(x);
     tempblock.display();
   }
 }
 
}

void mouseClicked(){
 for(int i = 0;i<maxCol; i++){
   for(int x=0; x<maxRow; x++){
     Block tempblock = (Block) blocks[i].get(x);
       if(dist(tempblock.blockx,tempblock.blocky,mouseX,mouseY) <=12.5){
         tempblock.activated = true;
         checkblock(i,x);
         for(int t = 0; t<adjlocs.length;t++){
           if(adjlocs[t] != null){
             checkblock(int(adjlocs[t].x), int(adjlocs[t].y));
             adjlocs[t] = null;
           }
         }
       }
   }
 }
 removeBlocks();
 pointer = 0;
 pointer2 = 0;
}
class Block{
 public float blockx;
 public float blocky;
 private float blocksize;
 public boolean activated;
 public int type;
 public boolean visible;

 Block(float x, float y, float _blocksize, int _type, boolean _visible){
   blockx = x;
   blocky = y;
   blocksize = _blocksize;
   activated = false;
   type = _type;
   visible=_visible;
 }

 void display(){
   if(visible == true){
     if(activated == false){
       strokeWeight(1);
       if(this.type == 0){
         stroke(0,80,250);
       }
       else if(this.type == 1){
         stroke(250,45,45);
       }
     }
     else if(activated == true){
       strokeWeight(2);
       if(this.type == 0){
         stroke(0,80,250);
       }
       else if(this.type == 1){
         stroke(250,45,45);
       }
     }
     if(this.type == 0){
       fill(0,80,250,75);
     }
     else if(this.type == 1){
       fill(250,45,45,75);
     }
     rectMode(CENTER);
     rect(blockx, blocky, blocksize,blocksize);
   }
   else if(visible == false){

   }
 }

 void gravity(){
   float grav = .1;
   for(int i=0;i<maxCol;i++){
     for(int x=0;x<maxRow-1;x++){
       if(dist(blocksList[i][x].blockx,blocksList[i][x].blocky,blocksList[i][x+1].blockx, blocksList[i][x+1].blocky) >25){
         blocksList[i][x].blocky += grav;
       }
//        if(blocksList[i][x] != null && blocksList[i][x+1] != null){
//          while(dist(blocksList[i][x].blockx,blocksList[i][x].blocky,blocksList[i][x+1].blockx, blocksList[i][x+1].blocky) >25){
//            blocksList[i][x].blocky += grav;
//          }
//        }
//        else if(blocksList[i][x+1] == null){
//          if(blocksList[i][x]!=null){
//            blocksList[i][x].blocky += grav;
//          }
//        }
     }
   }
 }
}

void checkblock(int col, int row){

 Block tempblock = (Block) blocks[col].get(row);
 Block topblock = (Block) blocks[col].get(row);
 Block bottomblock = (Block) blocks[col].get(row);
 Block leftblock = (Block) blocks[col].get(row);
 Block rightblock = (Block) blocks[col].get(row);
 //assign right
 if(col < maxCol-1 && blocks[col+1].size() >= blocks[col].size()){
   rightblock = (Block) blocks[col+1].get(row);
   if(rightblock.type == tempblock.type){
     if(rightblock.activated != true){
       rightblock.activated = true;
       adjlocs[pointer] = new PVector(col+1, row);
       pointer++;
     }
   }
 }
 //assign bottom
 if(row < maxRow-1 && blocks[col].size() > row){
   bottomblock = (Block) blocks[col].get(row+1);
   if(bottomblock.type == tempblock.type){
     if(bottomblock.activated != true){
       bottomblock.activated = true;
       adjlocs[pointer] = new PVector(col, row+1);
       pointer++;
     }
   }
 }
 //assign left
 if(col != 0 && blocks[col-1].size() >= blocks[col].size()){
   leftblock = (Block) blocks[col-1].get(row);
   if(leftblock.type == tempblock.type){
     if(leftblock.activated != true){
       leftblock.activated = true;
       adjlocs[pointer] = new PVector(col-1, row);
       pointer++;
     }
   }
 }
 //assign top
 if(row != 0){
   topblock = (Block) blocks[col].get(row-1);
   if(topblock.type == tempblock.type){
     if(topblock.activated != true){
       topblock.activated = true;
       adjlocs[pointer] = new PVector(col, row-1);
       pointer++;
     }
   }
 }
}
void removeBlocks(){
 for(int i=0;i<maxCol;i++){
   for(int x=0;x<maxRow;x++){
     Block tempblock = (Block) blocks[i].get(x);
     if(tempblock.activated == true ){
       loclist[pointer2] = new PVector(i,x);
       pointer2++;
     }
   }
 }
 for(int i = 0;i<loclist.length;i++){
   if(loclist[i] != null){
     blocks[int(loclist[i].x)].remove(int(loclist[i].y));
     loclist[i] = null;
   }
 }
}

Re: index out of bounds exception...not sure why
Reply #1 - Apr 8th, 2010, 1:13am
 
In general, you should be more precise when reporting an error message, although runtime errors are harder to point out since they refer to the generated .java file, not to the .pde file.
Fortunately, you have a self-sufficient program, not using external libraries or files, so we can quickly test it.

You have an exception like:
Code:
Exception in thread "Animation Thread" java.lang.IndexOutOfBoundsException: Index: 8, Size: 5
at java.util.ArrayList.RangeCheck(ArrayList.java:547)
at java.util.ArrayList.remove(ArrayList.java:387)
at sketch_apr08a.removeBlocks(sketch_apr08a.java:210)
at sketch_apr08a.mouseClicked(sketch_apr08a.java:69)
[...]

It means you try to access index 8 in an array list of size 5, in a remove element operation. So it is a logic issue.

Your code is relatively complex and missing comments, so it is hard to figure out the exact issue without a long analysis, but from a quick glance, the problem is probably in the line:
blocks[int(loclist[i].x)].remove(int(loclist[i].y));
If I understood correctly from my hasty reading, you store the positions of the blocks to remove, then you delete them. But when you remove a block from the middle of an ArrayList, the blocks after this one have their position shifted by one unit (the next one takes the place of the removed one, and so on).
A classical way to address this issue is to reverse the order of removal, deleting first the blocks near the end of the list, so blocks to delete won't move.

It is better with:
for (int i = loclist.length - 1; i >= 0; i--) {
but on further click, there is an issue in mouseClicked on the blocks[i].get(x); line, probably because you try to access a removed block.
Re: index out of bounds exception...not sure why
Reply #2 - Apr 8th, 2010, 1:20am
 
You're using ArrayLists...  I remember running into this problem when working on my Asteroids game.  The problem you've encountered happens when you try and change the contents of the ArrayList whilst iterating over it (e.g. removing an item from inside a for loop).  This changes the size of the list the loop is iterating over, but the limit you're using is the original size of the ArrayList, hence the indexOutOfBounds...

The answer is to not remove() from within the loop but instead place a marker on that object and handle the removal elsewhere.  With Asteroids I added a boolean property to my Body objects ('alive') and tested this in the object's draw method.  If false I called the object's remove method - this might simply remove it from the ArrayList, or might also create an explosion or some other event...
Page Index Toggle Pages: 1