# Crafting a Quincunx This week’s assignment for Crafting with Data was to “Get to know the normal distribution intimately by building your own quincunx or Galton box. You may use either physical materials or create an imaginative software simulation.” As unhandy as I am with Processing, I’m even more so with actual three-dimensional materials, so building a physical object was out of the question. Instead, I set out to write the simplest possible piece of code that would perform this task. Of course, my programming being what it is, it ended up not being simple at all. I hadn’t used Processing in months, except for the pong thing and then for a few minutes in Mashups the other day. In neither case was I working with graphics.

So, it seems I’ve been giving Processing a wide berth for the wrong reasons. The hardest thing was not the graphics, which are meant to be simple enough that artists can use them, but rather the application flow. It seemed pretty straightforward, but I did get my loops mixed up more than once, and I was unsuccessful at simplifying things by pulling subroutines (?) out into separate functions—couldn’t get the variables to talk to each other. And I was not about to try to relearn how to make a properly object-oriented application. Please. It was all I could do to figure out how to display text in the thing.

Also? Auto format in Processing.app still doesn’t work; it gets bent out of shape, claiming there’s an extra parenthesis somewhere, when there’s patently not. Very annoying.

—and here’s what I made it out of:

```int rounds = 3000; // number of times to drop the ball
int rows = 10;
int unit = 12;

float pickanumber;
int whichway;
int column;
int startrow;
int thisround = 1;
int xpos;
int ypos = unit * 4;
int[] totals = new int[rows + 1];
int totalxpos;
PFont font;
PFont fontbold;
String coltotal;

void setup()
{
size(300, 725);
background(255);
fill(0);
noStroke();
smooth();
ellipseMode(CENTER);
textAlign(CENTER);

}

void draw()
{
if (thisround > rounds)
{
noLoop();
}
else
{
column = 0;
background(255);
drawround();
thisround++;
ypos = unit * 4;
}
}

void drawround()
{
fill(0);
textFont(fontbold, 14); // font size of round counter
String roundheader = "Round " + thisround + " of " + rounds;
text(roundheader, width / 2, unit * 2);
textFont(font, 9); // font size of totals

for (int thisrow = 1; thisrow <= rows; thisrow ++)
{
// Decide which way the ball is shifting after this row.
pickanumber = random(1);
whichway = round(pickanumber); // a 1 sends the ball to the right

// Where does the first ball for this row go?
startrow = width / 2 - unit * (thisrow - 1);

// The number of dots in each row is the same as the row number.
for (int b = 0; b < thisrow; b++)
{

xpos = startrow + unit * 2 * b;
noStroke();

// What color should this ball be?
if (b == column)
{
if (whichway > 0)
{
fill(#535E1E); // green dot
}
else
{
fill(#680F18); // red dot
}
}
else
{
fill(200);
}
ellipse(xpos, ypos, unit, unit);
}

if (whichway > 0) // rolled a 1, so go to the right
{
column++; // where the ball is now; starts at zero
}
else
{
}

ypos = ypos + unit * 2;
}
// Where to start drawing the line of boxes?
totalxpos = startrow - unit;

for (int t = 0; t <= rows; t++)
{
// draw the box
fill(255);
stroke(200);
rectMode(CENTER);
rect(totalxpos, ypos, unit * 1.5, unit * 1.5);

// if the ball fell into this box, increment the total
if (column == t)
{
totals[t] ++;
}

// print the running total for this box
if (totals[t] > 0)
{
coltotal = str(totals[t]);
fill(0);
textAlign(CENTER);
text(coltotal, totalxpos, ypos + unit / 8 + 3); // the '+ 3' centers the totals vertically in the boxes

// draw a bar chart for this column
fill(200);
noStroke();
rectMode(CORNER);
rect(totalxpos - unit * 1.5 / 2, ypos + unit * 1.5, unit * 1.5, totals[t] / 2);
}
totalxpos = totalxpos + unit * 2;
}
}
```

It’d be nice to have controls on it so you can play with the variables—height in rows, number of rounds, framerate—through the app instead of having to monkey with the code. But I’m never going to make time to do that, so, oh, well.

This site uses Akismet to reduce spam. Learn how your comment data is processed.