Clickable 2d Grid

I got the code below to create a grid with an array. Now I want to be able to change the color of on square by clicking on it and also change it back when clicked again. How would I do that?

Right now the Color of the square is created in the class under “void display”. I assume that I first would need to move that into the constructor so i can access it from the main programm?

but how would I let the Program know wich square I clicked?


Cell[][] grid;


int cols = 25;
int rows = 25;

void setup() {
  size(500,500);
  grid = new Cell[cols][rows];
  for (int i = 0; i < cols; i++) {
    for (int j = 0; j < rows; j++) {
 
      grid[i][j] = new Cell(i*20,j*20,20,20,i+j);
    }
  }
}

void draw() {
  background(0);

  for (int i = 0; i < cols; i++) {
    for (int j = 0; j < rows; j++) {
     
      
      grid[i][j].display();
    }
  }
}

Studio.ProcessingTogether.com/sp/pad/export/ro.9ABG0RKl9D2Bx

Yea thats exactly what I’m looking for. But I don’t understand a single thing in that code

Could you point out which parts you don’t get it? :mag_right:

The code is way too complicated for me. I understand the click function. But how is the color changed In that code? 90% of everything in that code I have never seen. Fill(State? Color:ON…) what is that even supposed to mean?

The code is unfortunately way to advanced for me

The boolean field state keeps track whether a Square object is currently “on” (true) or “off” (false):

fill(state? COLOR_ON:COLOR_OFF); decides which color to pick based on field state:

Hello!

I think you use a class Cell that you don’t show here.

In the class add a variable state. It tells you when the field is clicked.

So in display () say if(state) fill(100); else fill(255);

In this way you evaluate state.

But how to set state? Do this in mousePressed() function please.

void mousePressed(){
For loop over the cells when mouse inside set state
}

Chrisir

here is my take on it:

Code
int w = 10, h = 10, scl = 60;
color on = color(255, 0, 0), off = color(0, 0, 255);
slot slots[][] = new slot[w][h];
void setup() { 
  size(600, 600); 
  for (int i = 0; i < w; i++) for (int j = 0; j < h; j++) slots[i][j] = new slot(i, j, false);
} 
void draw() {
  background(0);
  for(int i = 0; i < w; i++) for(int j = 0; j < h; j++) slots[i][j].display();
}
void mousePressed() {
  for(int i = 0; i < w; i++) for(int j = 0; j < h; j++) if(slots[i][j].isPressed(mouseX,mouseY)) slots[i][j].state = !slots[i][j].state;
}
class slot {
  int x, y;
  boolean state;
  slot(int x_, int y_, boolean state_) {
    x = x_;
    y = y_;
    state = state_;
  }
  void display() {
    fill( ((state)? on : off) );
    square(x*scl, y*scl, scl);
  }
  boolean isPressed(int mx, int my) {
    return ( floor(map(mx,0,width,0,w)) == x && floor(map(my,0,height,0,h)) == y);
  }
}

simplified…


//

Cell[][] grid;

int cols = 25;
int rows = 25;

void setup() {
  size(500, 500);

  grid = new Cell[cols][rows];
  for (int i = 0; i < cols; i++) {
    for (int j = 0; j < rows; j++) {
      grid[i][j] = new Cell(i*20, j*20, 20, 20, i+j);
    }
  }
}

void draw() {
  background(0);

  for (int i = 0; i < cols; i++) {
    for (int j = 0; j < rows; j++) {
      grid[i][j].display();
    }
  }
}

void mousePressed() {
  for (int i = 0; i < cols; i++) {
    for (int j = 0; j < rows; j++) { 
      if (grid[i][j].isPressed()) {
        //toggle
        grid[i][j].state = 
          ! grid[i][j].state;
      }
    }
  }
}

// =========================================================================

class Cell {

  int x, y;
  boolean state=false;
  int scl=20;

  Cell(int x_, int y_, 
    int a_, int b_, int id_) {
    x = x_;
    y = y_;
  }

  void display() {
    if (state)  
      fill( 255, 2, 2 ); 
    else fill( 255 );

    stroke(0); 

    rect(x, y, 
      scl, scl);
  }

  boolean isPressed() {
    if (  
      mouseX>x&&
      mouseY>y&&
      mouseX<x+20&&
      mouseY<y+20)
      return true; 
    else return false;
  }//method
  //
}//class
//

Your solution really helped me a lot. I now got a grid that can be clicked and clicked cells turn grey. Now what I want to archive is that when a cell is painted (grey) and all cells surrounding it also are active, the cell that is completely surrounded should have a circle in it.

For that I created a new boolean and also added the circle in the .display looking like that now:

class grid()....

boolean isSurrounded = false;

...

void display{

...

  if (isSurrounded) {
      fill(255, 0, 0);
      circle(x+10, y+10, h);
    }
}

but im not sure how to construct the boolean for isSurroundet(). How to tell the boolean to be true when all cells around it are active as well… Do you have an Idea?

when in the class each cell knows its pos in the grid (i,j)

boolean isSurrounded( int a, int b) {
  int count=0; 
  for (int i = -1; i <= 1; i++) {
    for (int j = -1; j <= 1; j++) {
      if (a+i >= 0 && a+i < cols &&  
        b+j >= 0 && b+j < rows && 
        ! ( i==0 && j==0) ) {
        if (grid[a+i][b+j].state) {
          count++;
        }
      }
    }
  }

  if (count==8) {
    return true;
  } else {
    return false;
  }
}

it doesn’t work for the corners or sides

entire code


//

Cell[][] grid;

int cols = 25;
int rows = 25;

void setup() {
  size(500, 500);

  grid = new Cell[cols][rows];
  for (int i = 0; i < cols; i++) {
    for (int j = 0; j < rows; j++) {
      grid[i][j] = new Cell(i*20, j*20, 
        20, 20, i, j);
    }
  }
}

void draw() {
  background(0);

  for (int i = 0; i < cols; i++) {
    for (int j = 0; j < rows; j++) {
      grid[i][j].display();
    }
  }
}

void mousePressed() {
  for (int i = 0; i < cols; i++) {
    for (int j = 0; j < rows; j++) { 
      if (grid[i][j].isPressed()) {
        //toggle
        grid[i][j].state = 
          ! grid[i][j].state;
      }
    }
  }
}

boolean isSurrounded( int a, int b) {
  int count=0; 
  for (int i = -1; i <= 1; i++) {
    for (int j = -1; j <= 1; j++) {
      if (a+i >= 0 && a+i < cols &&  
        b+j >= 0 && b+j < rows && 
        ! ( i==0 && j==0) ) {
        if (grid[a+i][b+j].state) {
          count++;
        }
      }
    }
  }
  if (count==8) {
    return true;
  } else {
    return false;
  }
}// 

// =========================================================================

class Cell {

  int x, y;
  boolean state=false;
  int scl=20;
  int i, j;
  int sclx, scly; 

  Cell(int x_, int y_, 
    int a_, int b_, 
    int i_, int j_) {
    x = x_;
    y = y_;

    sclx=a_;
    scly=b_; 

    i=i_;
    j=j_;
  }

  void display() {
    if (state)  
      fill( 255, 2, 2 ); 
    else fill( 255 );

    stroke(0); 

    rect(x, y, 
      sclx, scly);

    if (isSurrounded(i, j )) {
      fill(255, 0, 0);
      ellipse(x+10, y+10, 12, 12);
    }
  }

  boolean isPressed() {
    if (  
      mouseX>x&&
      mouseY>y&&
      mouseX<x+20&&
      mouseY<y+20)
      return true; 
    else return false;
  }//method
  //
}//class
//

New version:

  • When a field is not empty, it is not considered as being surrounded anymore (even when it has 8 occupied neighbors). (But this is not what you want, right?)
  • A surrounded corner or surrounded boeder cell is now recognized as surrounded

//

Cell[][] grid;

int cols = 25;
int rows = 25;

void setup() {
  size(500, 500);

  grid = new Cell[cols][rows];
  for (int i = 0; i < cols; i++) {
    for (int j = 0; j < rows; j++) {
      grid[i][j] = new Cell(i*20, j*20, 
        20, 20, i, j);
    }
  }
}

void draw() {
  background(0);

  for (int i = 0; i < cols; i++) {
    for (int j = 0; j < rows; j++) {
      grid[i][j].display();
    }
  }
}

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

void mousePressed() {
  // toggle state of a cell 
  for (int i = 0; i < cols; i++) {
    for (int j = 0; j < rows; j++) { 
      if (grid[i][j].isPressed()) {
        //toggle
        grid[i][j].state = 
          ! grid[i][j].state;
        return; // leave
      }
    }
  }
}

boolean isSurrounded( int a, int b) {
  // returns true when all (8) neighbour cells are occupied
  // This tests also if we are on a wall / corner. This counts as a occupied field.

  // When the field is not empty, it is not considered as being surrounded...
  if (grid[a][b].state) {
    return false; // leave
  }

  // first count occupied fields (and borders) 
  int count=0; 
  for (int i = -1; i <= 1; i++) {
    for (int j = -1; j <= 1; j++) {

      // This tests if we are on a wall / corner. This counts as a occupied field.  
      if ( ( ! fieldIsOK(a+i, b+j) )  && 
        (! ( i==0 && j==0) )) {
        //
        count++;
      }

      if (fieldIsOK(a+i, b+j)  && 
        ! ( i==0 && j==0) ) {
        if (grid[a+i][b+j].state) {
          // the next field is occupied 
          count++;
        }
      }
    }//for
  }//for

  // Eval count 
  if (count==8) {
    return true;
  } else {
    return false;
  }//else
}// 

boolean fieldIsOK(int ai, int bj) {
  // returns true when the field is a valid index pair x,y for the grid 
  if (ai >= 0 && ai < cols &&  
    bj >= 0 && bj < rows ) 
    return true; 
  else 
  return false;
}//

// =========================================================================

class Cell {

  int x, y;
  boolean state=false;
  int scl=20;
  int i, j;
  int sclx, scly; 

  Cell(int x_, int y_, 
    int a_, int b_, 
    int i_, int j_) {
    x = x_;
    y = y_;

    sclx=a_;
    scly=b_; 

    i=i_;
    j=j_;
  }

  void display() {
    if (state)  
      fill( 255, 2, 2 ); 
    else fill( 255 );

    stroke(0); 

    rect(x, y, 
      sclx, scly);

    if (isSurrounded(i, j )) {
      fill(255, 0, 0);
      ellipse(x+10, y+10, sclx-8, sclx-8);
    }
  }

  boolean isPressed() {
    // returns whether the mouse is inside the cell 
    if (  
      mouseX>x&&
      mouseY>y&&
      mouseX<x+20&&
      mouseY<y+20)
      return true; 
    else return false;
  }//method
  //
}//class
//

1 Like