Randomly coloring x amount of tiles within a grid

Hey guys,
Im working on a project for school where I have to randomly generate x amount of colored tiles within a grid. In my current code every tile in the grid randomly receives a red or blue color.
What do I need to change to ensure that for example only 10 red and 10 blue squares are colored in this 60x40 grid?

final int COLS = 60;
final int ROWS = 40;
int cellSize = 20;
int[][] generateItems = new int[COLS][ROWS];

void setup() {
  size(1200, 900);
  for ( int i = 0; i < COLS; i++) {
    for ( int j = 0; j < ROWS; j++) {
      generateItems[i][j] = int(random(1, 4));
      println(generateItems[i][j] = int(random(1, 4)));
    }
  }
}

void draw() {
  background(#FFFFFF);
  for ( int i = 0; i < COLS; i++) {
    for ( int j = 0; j < ROWS; j++) {
      int t = abs(generateItems[i][j]);
      if ( t < 1 ) {
      } else if ( t == 2 ) {
        fill(0, 0, 200);
        noStroke();
        rect(cellSize*i, cellSize*j, cellSize, cellSize);
      } else if ( t == 3 ) {
        fill(200, 0, 0);
        noStroke();
        rect(cellSize*i, cellSize*j, cellSize, cellSize);
      }
    }
  }
}

void mousePressed() {
  int x = int( mouseX / cellSize );
  int y = int( mouseY / cellSize );
  if ( x >= 0 && y >= 0 && x < 60 && y < 40 ) {
    generateItems[x][y] = generateItems[x][y] = 1;
  }
}

I’ve been stuck on this for a while so any help or advice is appreciated!

Hello and welcome to the forum!

Great to have you here!

your grid is of type int.

It could be of type color

Then you would assign a color to it in setup() and use it in draw().

Problem

The problem is that when you use random(4) to decide whether to set red, blue or white you have to count to 10 for red and blue separately. Very complicate

Solution

for example when you have an IntList colorList to support you in the goal of having 10 red and 10 blue. And the rest white.

So you fill the IntList

  • with 10 times 0 (for-loop), then
  • with 10 times 1 (for-loop) and
  • the rest (for loop with i < COLS*ROWS-20 ? ) with 2. Use append() command.

Then you shuffle the list. That’s the core idea. Use shuffle() command. Since shuffle() shuffles the entire list colorList randomly, we don’t need an additional random. So we can just read from colorList linear (from beginning to end) and we know, we still have 10 times 0, 10 times 1 and the rest 2 but in a random distribution. Nice.

Then in your nested for loop

void setup() {
  size(1200, 900);
  for ( int i = 0; i < COLS; i++) {
    for ( int j = 0; j < ROWS; j++) {

you have an additional variable k:

void setup() {
  size(1200, 900);
  int k=0; 
  for ( int i = 0; i < COLS; i++) {
    for ( int j = 0; j < ROWS; j++) {

    k++;

(Since you increase k every time, it just keeps on increasing, so it is an index for the entire grid.)

Use k as index for colorList to read linear from colorList. Use get() command.

Define the grid generateItems

Define the grid generateItems based on the content of colorList.

Now you can say

if(colorList.get(k)==0) {
    // set red 
    generateItems[i][j] = color(255,0,0);
}else if(colorList.get(k)==1) {
   // set blue
   ....
}
else {
    //set white
    ....
}

SEE https://www.processing.org/reference/IntList.html

Warm regards,

Chrisir

:wink:

2 Likes

Hey Chrisir!

Thanks for your fast reply. I’ll take a look at intLists, this seems like a good solution to my problem!

1 Like

Hey Chrisir,

So I took a look at IntLists + the advice you gave me. This should be able to solve my problem! But I did run into an issue.

IntList colorList;
final int ROWS = 60;
final int COLS = 40;
final int assignValues[][] = new int [ROWS][COLS];

void setup() {
  size(1200, 900);
  colorList = new IntList();
  for (int a = 0; a < 10; a++) {
    colorList.append(color(255, 0, 0));
  }
  for (int b = 0; b < 10; b++) {
    colorList.append(color(0, 0, 255));
  }
  for (int c = 0; c < ROWS*COLS - 20; c++) {
    colorList.append(color(255, 255, 255));
  }
  colorList.shuffle();
  println(colorList);

  int k = 0; 
  for ( int i = 0; i < COLS; i++) {
    for ( int j = 0; j < ROWS; j++) {
      k++;
      if (colorList.get(k)==0) {
        // set red 
        assignValues[i][j] = color(255, 0, 0);
      } else if (colorList.get(k)==1) {
        //set blue
        assignValues[i][j] = color(0, 0, 255);
      } else {
        //set white
        assignValues[i][j] = color(255, 255, 255);
      }
    }
  }
}

So this is what I’ve worked out so far. The values get randomly assigned etc but once I add in the part: if (colorList.get(k)==0) { etc it gives me an ArrayIndexOutOfBoundsException error.

Do you have any idea what I’m missing or doing wrong^^

Thanks again for your help!

Hi @arizona440

So, if I am not mistaken, your error happens because you are trying to access an element of your list that does not exist.

Lets check array and list dimensions. Notice that you declared:

final int ROWS = 60;
final int COLS = 40;
final int assignValues[][] = new int [ROWS][COLS];

but your for loop is switched when accessing the values in assignValue[i][j]

for ( int i = 0; i < COLS; i++) {
    for ( int j = 0; j < ROWS; j++) {
        assignValues[i][j]; //THIS SHOULD ACTUALLY BE: assignValues[j][i], j = ROWS and i = COLS
     }
}

Second,

  1. Your colorList has ROWS * COLS elements, correct?
  2. The nested for loops
 for ( int i = 0; i < COLS; i++) {
    for ( int j = 0; j < ROWS; j++) {

will iterate over ROWS * COLS times, but…
you are incrementing k, before accessing the element:

k++;
      if (colorList.get(k)==0) {

So when i = 0 and j = 0, you’ll have k = 1, which is not a problem, but when i = COLS - 1 and ROWS = -1 your k value will surpass the amount of element because you added plus 1 before access the variable, so your for nested loop should be:

int k = 0; 
  for ( int i = 0; i < COLS; i++) {
    for ( int j = 0; j < ROWS; j++) {
      
      if (colorList.get(k)==0) {
        // set red 
        assignValues[j][i] = color(255, 0, 0); //assignValues[j][i], j = ROWS and i = COLS
      } else if (colorList.get(k)==1) {
        //set blue
        assignValues[j][i] = color(0, 0, 255); //assignValues[j][i], j = ROWS and i = COLS
      } else {
        //set white
        assignValues[j][i] = color(255, 255, 255); //assignValues[j][i], j = ROWS and i = COLS
      }
    }
    k++; //Increment k in the end!
  }

Give it a try!
Best regards

2 Likes

Hello,

Hint:
https://processing.org/reference/IntList_size_.html

https://processing.org/reference/ArrayList.html

:)

1 Like

Hey @MiguelSanches!

This was indeed the problem. While remaking the code with Chrisir’s advice I must have at some point mixed up ROWS and COLS.

Thanks alot!

There are so many ways to do it!!

While I said to fill the IntList with 0,1,2 you filled it with the colors!! Alright!

Now we shuffle the colors.

But then you don’t have to use a long if…else if…else in draw.

Just copy the color:

  assignValues[j][i] = colorList.get(k);

But of course, k++ must come AFTER this line.

This works because color IS int in processing.

So I made assignValues of type color too.

Warm regards,

Chrisir


final int cellSize = 20;

IntList colorList;
final int ROWS = 60;
final int COLS = 40;
color assignValues[][] = new color [ROWS][COLS];

//-----------------------------------------------------------

void setup() {
  size(1400, 900);

  colorList = new IntList();
  for (int a = 0; a < 10; a++) {
    colorList.append(color(255, 0, 0));
  }
  for (int b = 0; b < 10; b++) {
    colorList.append(color(0, 0, 255));
  }
  for (int c = 0; c < ROWS*COLS - 20; c++) {
    colorList.append(color(255, 255, 255));
  }
  colorList.shuffle();
  println(colorList);

  int k = 0; 
  for ( int i = 0; i < COLS; i++) {
    for ( int j = 0; j < ROWS; j++) {

      assignValues[j][i] = colorList.get(k);
      k++;
    }//for
  }//for
}//func 

void draw() {
  background(#FFFFFF);
  for ( int i = 0; i < COLS; i++) {
    for ( int j = 0; j < ROWS; j++) {
      fill(assignValues[j][i]);
      //  noStroke();
      rect(cellSize*j+12, cellSize*i+12, 
        cellSize, cellSize);
    }//for
  }//for
}//draw

//-----------------------------------------------------------

void mousePressed() {
  int x = int( mouseX / cellSize );
  int y = int( mouseY / cellSize );
  if ( x >= 0 &&
    y >= 0 &&
    x < 60 &&
    y < 40 ) {
    assignValues[x][y] = color(0, 255, 0);
  }
}
//
2 Likes