While Loops

In these notes you will learn:

  • How to create an infinite loop using a while-loop.
  • How to write and trace while-loops that perform simple task such as incrementing variables.

Introduction

Suppose you want to print the numbers from 1 to 1000 on the screen. You could do it like this:

println(1);
println(2);
println(3);

// ...

println(1000);

Writing 1000 lines of code is pretty tedious. It’s easy to make a mistake, and it’s also inflexible — what if you wanted to print the numbers from 500 to 5000 instead?

A much better solution is to use a while-loop. A while-loop repeats a block of code zero or more times.

Infinite Loops

The simplest kind of loop is a loop that never stops, i.e. an infinite loop. We can use a while-loop to create an infinite loop like this:

while (true) {             // infinite loop
   println("Hello!");
}

It prints Hello! forever:

Hello!
Hello!
Hello!
Hello!
...

Loops that Stop

Suppose we want to print the numbers 1 to 10 on the screen using a while- loop. The standard technique for doing this is to use a variable, say i, to keep track of how many times the block of code in the while-loop has been executed. For example:

int i = 1;

while (true) {  // infinite loop
   println(i);
   ++i;  // adds 1 to i (same as i += 1)
}

println("done");

This loop prints this:

1
2
3
4
...

This illustrates the important idea of incrementing a variable inside a loop, but it is still an infinite loop that never stops.

How do we get the loop to stop? The condition at the top of the loop decides if the code block underneath it is executed or skipped. So far our while-loop condition has always been true:

while (true) {  // condition for this loop is "true": always executes
   // ...                                             the code block underneath
}

We can use any boolean expression (i.e. an expression that evaluates to either true or false) as the condition for a while-loop. For example:

int i = 1;

while (i <= 10) {
   println(i);
   ++i;
}

println("done");

Now the while-loop condition is i <= 10, which means that the block of code under the while-loop will only be executed when i <= 10 is true. If i <= 10 is false, then the loop stops and jumps down to the first statement after the loop (i.e. println("done")).

And that’s really all there is to while-loops: the condition at the top decides whether or not to execute the block of code underneath. When the condition is false the loop is over, i.e. it is terminated.

Tracing a while-loop

Look again at this loop:

int i = 1;

while (i <= 10) {
   println(i);
   ++i;
}

println("done");

The best way to understand loops is to “play computer” and trace the code by hand, keeping track of the value of i as you go. Tracing it by hand, you do something like this:

  • i is initially set to 1.
  • The first time the loop condition is checked, i is 1, and so i <= 10 is true. Thus println(i) is called, causing 1 to be printed. Then 1 is added to i, making it equal to 2.
  • After the code block is executed, the loop condition is checked again. Since i is 2, i <= 10 is true, and so 2 is printed and i is incremented to 3.
  • After the code block is executed, the loop condition is checked again. Since i is 3, i <= 10 is true, and so 3 is printed and i is incremented to 3.

You can see how the pattern continues. Eventually, i becomes 10. The loop condition i <= 10 is true, and so 10 is printed and i is incremented to 11.

The next time the loop condition is checked, i <= 10 is false because i is 11. A false loop condition makes the loop skip its body block and jump directly whatever statements follow the loop.

Tracing loops is a valuable skill that you should practice. Loops in real programs can get tricky, and tracing them by hand is often the best way to understand what it does.

Adding Objects to an ArrayList

In previous notes we saw code like this for adding a lot of bouncing ball objects to an ArrayList:

// ...

ArrayList<BouncingBall> ballList;  // initially null

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

  // create the initially empty ArrayList of BouncingBall objects
  ballList = new ArrayList<BouncingBall>();

  // add 10 bouncing ball's
  ballList.add(randomBouncingBall());
  ballList.add(randomBouncingBall());
  ballList.add(randomBouncingBall());
  ballList.add(randomBouncingBall());
  ballList.add(randomBouncingBall());
  ballList.add(randomBouncingBall());
  ballList.add(randomBouncingBall());
  ballList.add(randomBouncingBall());
  ballList.add(randomBouncingBall());
  ballList.add(randomBouncingBall());
}

void draw() {
  background(255);

  // render and update all the balls
  for(BouncingBall b : ballList) {
    b.render();
    b.update();
  }
}

A better approach is to use a while-loop:

// ...

int NUM_BALLS = 10;

void setup() {

   // ...

   int i = 0;
   while (i < NUM_BALLS) {
      ballList.add(randomBouncingBall());
      i += 1;
   }

}

// ...

The while-loop not only greatly shortens the code, but also makes it trivial to change the number of balls by setting NUM_BALLS.

Questions

  1. What does each of the following code fragments print?

    int a = 5;                // fragment 1
    while (a <= 10) {
       println(a);
       ++a;
    }
    
    
    int a = 5;                // fragment 2
    while (a < 10) {
       println(a);
       ++a;
    
    
    int a = 5;                // fragment 3
    while (a <= 10) {
       ++a;
       println(a);
    }
    
    
    int a = 5;                // fragment 4
    while (a < 10) {
       ++a;
       println(a);
    }
    
    
    int a = 5;                // fragment 5
    while (a != 10) {
       println(a);
       ++a;
    }
    
    
    int a = 5;                // fragment 6
    while (a != 10) {
       ++a;
       println(a);
       ++a;
    }
    
  2. What does each of the following code fragments print?

    int k = 5;                // fragment 1
    while (k > 1) {
       println(k);
       --k;
    }
    
    
    int k = -1;               // fragment 2
    while (k > -5) {
       println(k);
       --k;
    }
    
    
    int k = -1;               // fragment 3
    while (k > -5) {
       --k;
       println(k);
    }
    
  3. What does each of the following code fragments print?

    int b = 0;                // fragment 1
    while (b < 10) {
       println(b);
       b += 2;
    }
    
    
    int b = 0;                // fragment 2
    while (b <= 10) {
       println(b);
       b += 2;
    }
    
    
    int b = -10;              // fragment 3
    while (b < 0) {
       println(b);
       b += 3;
    }
    
    
    int b = 10;               // fragment 4
    while (b >= 0) {
       println(b);
       b -= 2;
    }
    
    int b = 0;                // fragment 5
    while (b < 10) {
       println(b);
       b *= 2;
    }
    
    
    int b = 1;                // fragment 6
    while (b < 10) {
       println(b);
       b *= 2;
    }
    
  4. Write a file loop that prints the following sequences of numbers. There should be exactly one println statement in the body of your while loop that prints one number of the sequence on each iteration.

    1. 1, 2, 3, 4, 5
    2. 5, 4, 3, 2, 1
    3. -1, -2, -3, -4, -5
    4. -5, -4, -2, -1
    5. 1, 3, 5, 7, 9
    6. 9, 7, 5, 3, 1
    7. -5, 0, 5, 10, 15
    8. 1, 1, 2, 2, 3, 3, 4, 4 (remember that there should be exactly one println statement in the body of your while-loop that prints exactly one number of the sequence)
    9. 1, -1, 2, -2, 3, -3, 4, -4 (remember that there should be exactly one println statement in the body of your while-loop that prints exactly one number of the sequence)
    10. -1, 1, -2, 2, -3, 3, -4, 4 (remember that there should be exactly one println statement in the body of your while-loop that prints exactly one number of the sequence)
  5. Explain why the following is not an infinite loop:

    int n = 1;
    while (n > 0) {
       println("loop");
       ++n;
    }
    

Code

class Sprite {
  float x;
  float y;
  float dx;
  float dy;

  void update() {
    x += dx;
    y += dy;
  }
}

class BouncingBall extends Sprite {
  float diam;
  color fillColor;

  void render() {
    pushMatrix();

    noStroke();
    fill(fillColor);

    ellipse(x, y, diam, diam);

    popMatrix();
  }

  void update() {
    x += dx;
    y += dy;

    // hit top?
    if (y - diam / 2 < 0) {
      y = diam / 2;
      dy = -dy;
    }

    // hit bottom?
    if (y + diam / 2 > height) {
      y = height - diam / 2;
      dy = -dy;
    }

    // hit left?
    if (x - diam / 2 < 0) {
      x = diam / 2;
      dx = -dx;
    }

    // hit right?
    if (x + diam / 2 > width) {
      x = width - diam / 2;
      dx = -dx;
    }
  }
}

BouncingBall randomBouncingBall() {
  BouncingBall ball = new BouncingBall();
  ball.x = random(100, 200);
  ball.y = random(100, 200);
  ball.dx = random(-3, 3);
  ball.dy = random(-3, 3);
  ball.diam = random(50, 150);
  ball.fillColor = color(random(255),
  random(255),
  random(255));
  return ball;
}

int NUM_BALLS = 10;

ArrayList<BouncingBall> ballList;  // initially null

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

  // create the initially empty ArrayList of BouncingBall objects
  ballList = new ArrayList<BouncingBall>();

  int i = 0;
  while (i < NUM_BALLS) {
    ballList.add(randomBouncingBall());
    i += 1;
  }
}

void draw() {
  background(255);

  // render and update all the balls
  for (BouncingBall b : ballList) {
    b.render();
    b.update();
  }
}

void mousePressed() {
  BouncingBall b = randomBouncingBall();
  b.x = mouseX;
  b.y = mouseY;
  ballList.add(b);
}