Fun grid design

Using an array and randomizing the elements of the design (circles, squares, dots, lines). The hard part was using a bunch of if-statements so that there won’t be overlap of the elements (see the update and display functions below to get the idea).

void update() {
    line1 = random(1) < bias;
    line2 = random(1) < bias;
    line3 = random(1) < bias;
    line4 = random(1) < bias;
    line5 = random(1) < bias;
    line6 = random(1) < bias; 
    line7 = random(1) < bias;
    line8 = random(1) < bias;
    dot1 = random(1) < bias;
    dot2 = random(1) < bias;
    dot3 = random(1) < bias;
    dot4 = random(1) < bias;
    dot5 = random(1) < bias;
    dot6 = random(1) < bias;
    dot7 = random(1) < bias;
    dot8 = random(1) < bias;
    dot9 = random(1) < bias;
    circle1 = random(1) < bias;
    circle2 = random(1) < bias;
    circle3 = random(1) < bias;
    circle4 = random(1) < bias;
    circle5 = random(1) < bias;
    circle6 = random(1) < bias;
    circle7 = random(1) < bias;
    circle8 = random(1) < bias;
    circle9 = random(1) < bias;
    square1 = random(1) < bias;
    square2 = random(1) < bias;
    square3 = random(1) < bias;
    square4 = random(1) < bias;
    square5 = random(1) < bias;
    square6 = random(1) < bias;
    square7 = random(1) < bias;
    square8 = random(1) < bias;
    square9 = random(1) < bias;
    rectblank1 = random(1) < bias;
    rectblank2 = random(1) < bias;
    rectblank3 = random(1) < bias;
    rectblank4 = random(1) < bias;
    triblank1 = random(1) < bias;
    triblank2 = random(1) < bias;
    triblank3 = random(1) < bias;
    triblank4 = random(1) < bias;
    triblank5 = random(1) < bias;
    triblank6 = random(1) < bias;
    triblank7 = random(1) < bias;
    triblank8 = random(1) < bias;
  }


void display(){
  
    if (squared){
      // Draw squares:
      noFill();
      stroke(hu, sa, br);
      strokeWeight(us/28.57); // sets internal shape line width
      rectMode(CENTER);
    
      if (square1 && !circle1) {rect(x-us/4, y-us/4, us/6.67, us/6.67);}
      if (square2 && !circle2) {rect(x, y-us/4, us/6.67, us/6.67);}
      if (square3 && !circle3) {rect(x+us/4, y-us/4, us/6.67, us/6.67);}
  
      if (square4 && !circle4) {rect(x-us/4, y, us/6.67, us/6.67);}
      if (square5 && !circle5) {rect(x, y, us/6.67, us/6.67);}
      if (square6 && !circle6) {rect(x+us/4, y, us/6.67, us/6.67);}
  
      if (square7 && !circle7) {rect(x-us/4, y+us/4, us/6.67, us/6.67);}
      if (square8 && !circle8) {rect(x, y+us/4, us/6.67, us/6.67);}
      if (square9 && !circle9) {rect(x+us/4, y+us/4, us/6.67, us/6.67);}
    }
    
    
  
    if (round) {
      // Draw circles:
      noFill();
      stroke(hu, sa, br);
      strokeWeight(us/28.57); // sets internal shape line width
      ellipseMode(CENTER);
    
      if (circle1 && !square1) {ellipse(x-us/4, y-us/4, us/5.33, us/5.33);}  
      if (circle2 && !square2) {ellipse(x, y-us/4, us/5.33, us/5.33);}
      if (circle3 && !square3) {ellipse(x+us/4, y-us/4, us/5.33, us/5.33);}
  
      if (circle4 && !square4) {ellipse(x-us/4, y, us/5.33, us/5.33);}
      if (circle5 && !square5) {ellipse(x, y, us/5.33, us/5.33);}
      if (circle6 && !square6) {ellipse(x+us/4, y, us/5.33, us/5.33);}
  
      if (circle7 && !square7) {ellipse(x-us/4, y+us/4, us/5.33, us/5.33);}
      if (circle8 && !square8) {ellipse(x, y+us/4, us/5.33, us/5.33);}
      if (circle9 && !square9) {ellipse(x+us/4, y+us/4, us/5.33, us/5.33);}
    }
    
    
  
    
  
    if (blanked){
      // draw blanks:
      fill(bg);
      stroke(bg);
      strokeWeight(1);
      rectMode(CORNERS);
  
      if ((rectblank1 && !dot2) && (!dot5 && !dot8)) {rect(x-us/2.2, y-us/2.2, x+us/2.2, y);}
      if ((rectblank2 && !dot4) && (!dot5 && !dot6)) {rect(x-us/2.2, y-us/2.2, x, y+us/2.2);}
      if ((rectblank3 && !dot2) && (!dot5 && !dot8)) {rect(x+us/2.2, y+us/2.2, x, y-us/2.2);}
      if ((rectblank4 && !dot4) && (!dot5 && !dot6)) {rect(x+us/2.2, y+us/2.2, x-us/2.2, y);}
  
      fill(bg);
      stroke(bg);
      strokeWeight(1);
  
      if ((triblank1 && !dot1) && (!dot5 && !dot2)) {triangle(x, y, x-us/2.2, y-us/2.2, x, y-us/2.2);}
      if ((triblank2 && !dot1) && (!dot5 && !dot4)) {triangle(x, y, x-us/2.2, y-us/2.2, x-us/2.2, y);}
  
      if ((triblank3 && !dot3) && (!dot5 && !dot2)) {triangle(x, y, x+us/2.2, y-us/2.2, x, y-us/2.2);}
      if ((triblank4 && !dot3) && (!dot5 && !dot6)) {triangle(x, y, x+us/2.2, y-us/2.2, x+us/2.2, y);}
  
      if ((triblank5 && !dot7) && (!dot5 && !dot4)) {triangle(x, y, x-us/2.2, y+us/2.2, x-us/2.2, y);}
      if ((triblank6 && !dot7) && (!dot5 && !dot8)) {triangle(x, y, x-us/2.2, y+us/2.2, x, y+us/2.2);}
  
      if ((triblank7 && !dot9) && (!dot5 && !dot6)) {triangle(x, y, x+us/2.2, y+us/2.2, x+us/2.2, y);}
      if ((triblank8 && !dot9) && (!dot5 && !dot8)) {triangle(x, y, x+us/2.2, y+us/2.2, x, y+us/2.2);}
    }
  
    if (round){
      // Draw dots:
      ellipseMode(CENTER);
      fill(hu, sa, br);
      noStroke();
  
      if (dot1 && !line1) {ellipse(x-us/4, y-us/4, us/16.67, us/16.67);}
      if ((dot2 && !line4) && (!rectblank1 && !rectblank3)) {ellipse(x, y-us/4, us/16.67, us/16.67);}
      if (dot3 && !line6) {ellipse(x+us/4, y-us/4, us/16.67, us/16.67);}
  
      if ((dot4 && !line2) && (!rectblank2 && !rectblank4)) {ellipse(x-us/4, y, us/16.67, us/16.67);}
      if (dot5) {ellipse(x, y, us/16.67, us/16.67);}
      if ((dot6 && !line7) && (!rectblank2 && !rectblank4)) {ellipse(x+us/4, y, us/16.67, us/16.67);}
  
      if (dot7 && !line3) {ellipse(x-us/4, y+us/4, us/16.67, us/16.67);}
      if (dot8 && !line5) {ellipse(x, y+us/4, us/16.67, us/16.67);}
      if ((dot9 && !line8) && (!rectblank1 && !rectblank3)) {ellipse(x+us/4, y+us/4, us/16.67, us/16.67);}
    }
  
    if (lined){// Draw lines:
      noFill();
      stroke(hu, sa, br);
      strokeWeight(us/40);
      strokeCap(ROUND);
  
      if (line1 && !dot1) {line(x, y, x-us/2.25, y-us/2.25);}
      if (line2 && !dot4) {line(x, y, x-us/2.25, y);}
      if (line3 && !dot7) {line(x, y, x-us/2.25, y+us/2.25);}
  
      if (line4 && !dot2) {line(x, y, x, y-us/2.25);}
      if (line5 && !dot8) {line(x, y, x, y+us/2.25);}
  
      if (line6 && !dot3) {line(x, y, x+us/2.25, y-us/2.25);}
      if (line7 && !dot6) {line(x, y, x+us/2.25, y);}
      if (line8 && !dot9) {line(x, y, x+us/2.25, y+us/2.25);}  
    }
  
    // Draw border:
    if (border) {
      noFill();
      stroke(hu, sa, br);
      strokeWeight(us/40); // sets line width
      rectMode(CENTER);
      rect (x, y, us/1.1, us/1.1); // border line
    }
  }
11 Likes

That is very cool!!
By the way, I’m a novice coder and am wondering what “bias” is / or does?
I don’t see this on the processing.org reference page.

1 Like

I’m novice too (my first processing sketch was from Dec 4). Bias is a variable I used that can be changed from 0.0 to 1.0 and changes the likelihood of more shapes appearing. So if it is at zero we see only the border of each unit (which always displays). And as it increases it gets more complex until they start to compete more and only the center dot remains when it reaches one. This is bias gradually going from 0.0 to 1.0:

griddesign

1 Like

Novice, too. And I think it’s cool, too. There must be some way that the dots, lines and ellipses can be one variable each that iterates in a for loop.

1 Like

Beautiful project. I love the design, particularly the intermediate erasure steps.

One point to note: currently what update() does is generate booleans, which are equivalent to bits – true or false, 1 or 0. You generate 8 bits for line, 9 for dot, 9 for circle, 9 for square, 4 for rectblank, and 8 for triblank – that’s 8+9+9+9+4+8 = 47 bits, which you then use for drawing.

There are other ways to do this than 47 inidividually named variables. One is a method that returns random boolean arrays.

boolean[] randb(int count, float bias) {
  boolean[] result = new boolean[count];
  for (int i=0; i<count; i++) {
    result[i] = random(1) < bias ;
  }
  return result;
}

You can then do this:

void update() {
  boolean[] lines = randb(8);
  boolean[] dots = randb(9);
  boolean[] circles = randb(9);
  boolean[] square = randb(9);
  boolean[] rectblank = randb(4);
  boolean[] triblank = randb(8);
}

Note that these values are then accessed with zero-indexes – so rectblank[3] rather than rectblank4.

If you create a class object, like Tile, then you could also keep all your layer data in a single boolean[6][] data array. So Tile t = new Tile(); now you add methods like t.circle(3) or t.circles() and these methods can retrieve specific values or groups of values from your boolean[][] array.

Performance isn’t an issue, but if you want to optimize generating random bits with bias, there are lots of ways to do it. Right now each random() call is generating 32 bits of random (an integer is 32 bits) and the measuring it and storing 1 bit. Your approach works just fine, but if you want to do a lot of this in the future with different bias profiles – and/or you need to make it higher performance – then check out previous discussion here:

2 Likes

That looks pretty neat and reminds me of a circuit board (electronics).

In fact if you wrote an evaluation function you could have it try to generate a grid where all the tiles match on the edges or where just a line segment on one has to match with a line segment on the other. You could even make a game out of it where tiles can be moved/swapped and score people on how many they can get to match nicely before a timer ends.

P.S.
Would make an interesting desktop background too.

Those are good ideas. The idea first came to try and make an alien alphabet that has a square structure like Mayan or Chinese characters.

I do want to work on an evaluation function for another tile laying project I have planned.

Thanks! I’ve been pretty bad at optimizing my code and that is something I want to get better at especially as I start to get more lag with projects.

Hi guys!

Great patterns, I absolutely love them! :blush:

Got a version of my own, have changed the rules though :wink:

2 Likes

Great!

So it looks like the lines are going through the dots, behind the shapes (shapes are filled in?), and you got rid of the blank parts, anything else?

Yes, each of the nine shapes can be either empty, or a square, or a circle, or a diamond. The shapes must look of the same size (area).

So in total there must be as few as 8+2*9+9=35 bit number of variants :slight_smile:

That math doesn’t seem quite right. Even if you ignore lines and dots, you have four possible choices (empty, circle, square, diamond) in each of nine positions. So that’d be 4^9 different variants, wouldn’t it?

that’s right. 4 variants, described by 2-bit number (00b, 01b, 10b, 11b), hence 2*9 bits per figure (which gives 2^18 variants), plus 8 bits for lines and plus 9 bits for dots. 2^35 variants in total.

Alright. I found it confusing because the way you stated it made it seem like you meant there were 35 variants. Units are important after all. That’s an awful lot of options.

I used 3 different, 2D (3x3) boolean arrays to keep track of the lines, but I suppose that you could create one, 3D (3x3x3) boolean array if you really wanted to. I liked this design so much, I adjusted the bias of the square objects depending on the y-position of the “Square” to create a gradient effect. Looks pretty cool for a phone background.

3 Likes