Array Index Out of Bounds error on Array List

I’m creating a random item generator from an array list. When I get down to an empty list, I want a ‘gameOver’ function to run, but I get an Array Index Out of Bounds error. I’m wondering if I have a variable issue when the list is empty. I’m posting all the code here (sorry, first post, don’t know if there’s a better way to do this):

StringList names;
String [] list = {"apple","orange","grape","banana","lemon"};
String item;
int s = 1;
int i;
int x;

void setup(){
  size(300,300);
  names = new StringList(list);
  textAlign(CENTER);
  textSize(60);
  fill(255);
  background(0);
}

void randomSelect(){
  int s = names.size();
  print("(" + s + ") ");
  println(list);
  int x = int(random(s));
  item = names.get(x);
  println("Name Removed: " + item);
  fill(random(255),random(255),random(255));
  text(item, width/2,height/2);
  names.remove(x);
  s = s - 1;
  String[] newList = names.array();
  list = newList;
  print("(" + s + ") ");
  println(list);
  println();
}

void mouseClicked(){
  background(0);
  if(s > 0){
    randomSelect();
  }else{
    gameOver();
  }
}

void gameOver(){
  background(0);
  textSize(35);
  text("Out of Names", width/2,height/2);
}

void draw(){ 
}
1 Like

I’m sure that someone will tell you to format your code, you can do that by highlighting your code and pressing Control + Shift + C. What I did was add to your code:

if(names.size() > 0) 
 {
names.remove(x);
 }
if(names.size() == 0 )
 {
   gameOver();
 }

You’re getting an array index out of bound error, because when you remove the last item in your list, and then you try removing the object at the index of x, there is nothing to be removed. And then I just had an if statement say that if the size is zero, then to show your gameOver() function.

Hopefully this helps? If you have any more questions I would love to help, and please don’t mind keeping us updated on your project. (P.S. Do not forget to format your code next time :smiley: )

EnhancedLoop7

2 Likes

Thank you!! Super helpful. And thanks for the format help.

Next Q: How can I reset the array list to its original items with a mouse click?

Great thanks.

1 Like

How about this:

you first create a global variable like this:

String[] originalList = {"apple", "orange", "grape", "banana", "lemon"};

Then you add a function that duplicate your list:

String[] duplicateOriginalList() {
  String[] result = new String[originalList.length];
  for(int i = 0; i < originalList.length; i++) {
    result[i] = originalList[i];
  }
  return result;
}

All you have to do then is add the following line in your setup() function and just after your gameOver() call.

list = duplicateOriginalList();

Probably not the best and the most efficient way to do it but it is quick to implement and you don’t have to redo all of your code :slight_smile:

String[] originalArray = { "apple", "orange", "grape", "banana", "lemon" };
String[] clonedArray = originalList.clone();
3 Likes

Hoooo that’s the one I was looking for! :slight_smile:
I was trying .copy() with no success… :roll_eyes:

1 Like

And when the times comes to reset clonedArray back to the contents of originalArray, use arrayCopy(): :copyright:

arrayCopy(originalArray, clonedArray);

Also be aware that such cloning & copying techniques are shallow! :sweat:
And they should be used only for primitive and immutable datatypes! :warning:

Docs.Oracle.com/javase/10/docs/api/java/lang/Object.html#clone()

Thus, this method performs a “shallow copy” of this object, not a “deep copy” operation.

2 Likes

Good to point out!
I remember there was a thread last week about an implementation of the game of life where the behavior was weird because of that shallow copy.

Great help. Clone works well, but I wasn’t able to make arrayCopy work. I did patch together a way to get it to restart. But it only runs one more time, so something is amiss.

StringList fruits;
StringList clones;
String [] list = {"apple","orange","grape","banana","lemon"};
String [] clonedList = list.clone();
String item;
int i;
int x;

void setup(){
  size(300,300);
  fruits = new StringList(list);
  clones = new StringList(clonedList);
  textAlign(CENTER);
  fill(255);
  background(0);
}

void randomSelect(){
  textSize(60);
  print("list(" + fruits.size() + ") ");
  println(list);
  print("clonedList(" + clones.size() + ") ");
  println(clonedList);
  int x = int(random(fruits.size()));
  item = fruits.get(x);
  println("Name Removed: " + item);
  fill(255,0,0);
  text(item, width/2,height/2);
  fruits.remove(x);
  String[] newList = fruits.array();
  list = newList;
  print("(" + fruits.size() + ") ");
  println(list);
  println();
}

void mouseClicked(){
  background(0);
  if(fruits.size() > 0){
    randomSelect();
  }else if(fruits.size() == 0){
    gameOver();
    list = clonedList;
    fruits = clones;
  }else if(list == clonedList){
    randomSelect();
  }
}

void gameOver(){
  background(0);
  textSize(35);
  fill(0,0,255);
  text("Out of Names", width/2,height/2);
}

void draw(){ 
}

You are making it sooo complicated :smile:

Here something that is working with explanations. Hope it helps:

StringList originalFruits; // Will always contain the list of all the fruits
StringList fruits; // Will be the array that we use to get a new random fruit

void setup(){
  // Initializing both list
  originalFruits = new StringList("apple","orange","grape","banana","lemon");
  fruits = originalFruits.copy(); //It works because we are using string, It would't with custom classes
}


void randomSelect(){
  int idx = (int)random(fruits.size()); // Get a random index from 0 to the size of the array
  println(fruits.get(idx)); // Write in the console the name of the random picked fruit
  fruits.remove(idx); // Remove that fruit from the list since we dan't want to pick it again
}


void mouseClicked(){
  if(fruits.size() > 0) { // While there is still some fruit to pick we want to pick one
    randomSelect(); // So we pick one
  } else { // On the other case it means that we picked everything
    println("GAME OVER"); // So we are game over
    fruits = originalFruits.copy(); // And we need to fill the list of fruit again
  }
}


void draw(){ 
  
}
1 Like

Thanks! That was super helpful! Less is more.:grinning: