EARTH 801
Computation and Visualization in the Earth Sciences

Lesson 2: For loops

PrintPrint

Syntax introduced: for, <, {}, !<, >, !>, =, !=, string

0. Use a for loop to make repetitive calculations

Let's say it's a thunderstorm and we want to draw a whole bunch of our stylish lightning bolts to the screen. Luckily computers were built precisely to make repetitive calculations quickly. One way to take advantage of a computer's ability to do this is with a for loop. Check out the program below.

// use a for loop to draw several lightning bolts

size(400, 200);
background(0);
noStroke();
smooth();
fill(250, 230, 5);
int y = 20;
for (int i = 0; i < 400; i = i + 40) {
   beginShape();
   vertex(i, y);
   vertex(i, y + 50);
   vertex(i + 10, y + 40);
   vertex(i, y + 100);
   vertex(i + 10, y + 90);
   vertex(i, y + 160);
   vertex(i + 40, y + 65);
   vertex(i + 30, y + 75);
   vertex(i + 40, y + 25);
   vertex(i + 30, y + 35);
   vertex(i + 40, y);
   endShape(CLOSE);
}

The major new thing in this program is the section that goes:

for (int i = 0; i < 400; i = i + 40) {

...some commands

}

The line begins with the command for and then inside the parentheses are three parts, separated by semicolons.

Part 1 is the initialization

The part that says int i = 0; initializes the variable to loop over. In our program we are naming that variable i and setting it equal to zero.

Part 2 is the test

The next part that says i < 400; is a test. If the test is true, all the commands inside the curly braces are executed one at a time in order using the value of the loop variable wherever that variable appears. If the test fails, Processing ignores all the commands inside the curly braces and moves along to the rest of the program. In our program that test checks to see whether the value of the loop variable is less than 400 or not.

Part 3 is the increment

The third part that says i = i + 40 is the increment. When the for loop finishes the first time using the initial value of the loop variable, it goes back to the top of the for loop, increments the loop variable by the amount indicated (it adds 40 in this program), then it reassigns the variable to the new value. It checks if the test is still true, and if it is, it executes all the commands inside the curly braces with the new value of the loop variable. It repeats incrementing and executing until the test fails, and then it moves on and doesn't try to execute the for loop any more times.

processing code. if you need a transcription, contact eliza
Screenshot of a portion of a program that has a for loop, showing the initialization, test, and increment.

So put it all together and here is what this for loop does. It starts out with i = 0; It runs all the commands inside the curly braces using 0 every time it sees an "i." Then it adds 40, checks whether 40 is less than 400. It is, so it runs all the commands inside the curly braces using 40 every time it sees an "i". Then it adds 40, checks whether 80 is less than 400. It is, so it runs all the commands inside the curly braces using 80 every time it sees an "i." This goes on until i gets to 400 or higher. When that happens, Processing skips all the commands inside the curly braces and moves on to see if there are any commands to run after the curly braces.

What all this accomplishes is to draw the lightning bolt over and over again, each time moving it 40 pixels to the right. See how much trouble we have saved by writing a loop rather than writing multiple beginShape/endShape chunks!

display produced by program above.
Screenshot of the output of the new lightning bolt program.

1. More details about for loops

The initial variable can be a negative, zero, or positive. You can declare the variable before the for loop starts. The test can involve any relational operator, which is a fancy way of saying anything that compares two values. We will learn more about relational operators later but here are the most common ones:

  • less than, not less than: <, !<
  • greater than, not greater than: >, !>
  • equal to, not equal to: =, !=

The increment can be anything you want and it can be positive or negative.

Beware the infinite loop!

When you set up a for loop pay attention so that you don't write a loop that will never terminate. For example, what if I wrote the following loop:

for (int i = 10; i < 200; i = i - 10)

Bad trouble! Why? The initial value of i is 10, and then I am decreasing the value of i by 10 in the increment portion. But, my test checks whether or not the value of i is less than 200 and if it is, to go ahead and execute the loop. The value of i will never exceed 200 since i is getting more negative all the time, so this loop will never end because the test will never fail.

Nested loops

You can write for loops inside of other for loops. I think of this kind of thing kind of like tiling a cookie tray with the dough for a batch of cookies. Let's say you've made enough dough for 1 dozen cookies and you have a cookie tray. Here's a way to think of a pair of nested loops that explains how to put the dough blobs on the tray into 4 columns of 3 blobs each. (I think following along with my written description is a spatial visualization exercise, what do you think?)You go to first position in the upper left corner of the tray, then you execute a loop 3 times so that at the end of the loop, you have put 3 dough blobs on the tray in a column. That loop finishes and then you move one position to the right. You execute the same loop three more times so that you make a new column of dough blobs next to the first column. Keep going until you've got four columns with three cookies in each column. Here's how you'd write in Processing what I just explained in English.

int doughBlobSize = 20; 
for (int xpos = 10; xpos < 100; xpos = xpos + 25) {
   for(int ypos = 10; ypos < 100; ypos = ypos + 40) {
      println("xpos =" + xpos, "ypos =" + ypos);
      ellipse(xpos, ypos, doughBlobSize, doughBlobSize); 
   } 
}

I put the println() command in there so that when the program runs, you can check that the loops are doing what you thought they were doing. In general, sticking a println() command into your code somewhere is a good idea when you get unexpected output or an error and you want to double check that variables have the values you thought they did.

Let me break down the syntax println("xpos =" + xpos, "ypos =" + ypos);

The part that goes "xpos =" says to print the string xpos =

The part that goes + xpos says to print the value assigned to the variable named xpos

The comma tells Processing to put in a white space

The part that goes "ypos =" says to print the string ypos =

The part that goes + ypos says to print the value assigned to the variable named ypos

The commands are executed very fast but that println command gets executed 12 times, and each time the value of xpos and ypos have changed so it prints the new value to the screen. If you look at all the values in the console and cross-check that information with the display window output, you should be able to see the order in which the position of each dough blob was determined, even though they all get plotted at once in the blink of a human eye.

A screenshot of the program and its output:

Screenshot of a Processing program demonstrating a nested for loop

A program demonstrating a nested for loop. Click for text.

Code Displayed

//12 cookies on a tray

int doughBlobSize=20;

for (int xpos=10;xpos<100;xpos=xpos+25) {
   for (int ypos=10;ypos<100;ypos=ypos+40){
      println("xpos=" +pos, "ypos=" +ypos);
      ellipse(xpos,ypos,doughBlobSize,doughBlobSize);
   }
}

Output Displayed

xpos=10 ypos=10
xpos=10 ypos=50
xpos=10 ypos=90
xpos=35 ypos=10
xpos=35 ypos=50
xpos=35 ypos=90
xpos=60 ypos=10
xpos=60 ypos=50
xpos=60 ypos=90
xpos=85 ypos=10
xpos=85 ypos=50
xpos=85 ypos=90

There is also a pop-up window displayed showing 3 rows of 4 white circles (or 4 columns of 3 white circles, depending on your point of view).

Quiz yourself

How would you write the same program but instead of filling up a column and moving to the next column, you filled up the top row, then moved down to the next row?

Click for answer...

If your answer was to switch the order of the two loops and leave the rest of the program alone, then you are right!

//12 cookies on a tray

int doughBlobSize=20;

for(int ypos = 10; ypos < 100; ypos = ypos + 40) {
   for (int xpos = 10; xpos < 100; xpos = xpos + 25) {
      println("xpos =" + xpos, "ypos =" + ypos);
      ellipse(xpos, ypos, doughBlobSize, doughBlobSize);
   }
}

One more example

size(200, 200);
stroke(255);
line(10, 0, 10, 100);
stroke(0);
for (int i = 10; i < 200; i = i + 10) {
   println(i);
   fill(i);
   ellipse(i, i, 10, 10);
}
stroke(255);
line(30, 0, 30, 100);

This program first draws a white vertical line, then it starts a loop in which it draws a diagonal series of circles, each one lighter in color that the last. Then it leaves the loop and draws another vertical white line. This program demonstrates loops and command order. You can tell that the first white line was set before the loop started because the circles plot on top of it. The second white line came after the loop because it is drawn on top of the circles. The circles go in a diagonal line instead of tiled because I am incrementing both x and y at the same time instead of nesting one loop inside another loop.

display window output of a Processing program demonstrating loops and command order

Exercises

2.5 Rewrite the dough blob program so that you place the blobs in the same configuration, but you start from the bottom right corner and work upwards and to the left.

2.6 Use at least one for loop to draw your custom shape from Exercise 2.4 several times.

Turning in your work

Turn in Exercise 2.6 to the Lesson 2 dropbox by the due date indicated on this lesson's overview page. Here's what I am looking for in your program: correct use of beginShape(), endShape(), and vertex(), use of variables to set the vertices, and correct use of a for loop to draw the shape multiple times. Name your file lastname2.6.pde