Lecture 13

Agenda

Announcements

http://www.cns.uni.edu/~jacobson/061/applets/PurpleRain/PurpleRain.html

Back to Pong

Back to Pong for just a quick look.

Demo: Pong

The MovingBall class is included on the above page. Some things to notice, in case they weren't clear at the end of last class:

    public static double getTime()
    

It does not need to specify an object and returns the current time in milliseconds.

More on loops

Now that we have seen how important loops are in ActiveObjects, we step back and discuss more complex loops.

Here's an example where there is more than one variable can be changing in a loop. Consider the code to a constructor to draw a laundry basket, and demo of that basket:

Demo: BasketDemo

Notice that because botLineX increases more slowly than topLineX, the lines are not parallel.

The program below generates a picture of a scarf wherever the user clicks.

Demo: Knitting a Scarf

If you look carefully at the pictures generated, you will see that the scarf is formed by overlapping circles. It is easiest to develop this by first writing code to generate a row.

    // draws a scarf with upper left at point of click
    public void onMouseClick( Location point )
    {
        double x = point.getX();
        double y = point.getY();    // x and y positions of the next "stitch"
        
        int numCols = 0;
        
        while (numCols < SCARF_WIDTH) {
          new FramedOval(x, y, DIAMETER, DIAMETER, 
                         canvas).setColor(Color.green);
          x = x + X_DISP;
          numCols = numCols + 1;
        }
    }

Each time through the loop we increase the value of x as well as bump up numCols.

That wasn't too hard, but now we'd like to create successive rows. Each time we start a new row, there are a number of things that we will need to take care of:

  1. We need to reset the value of x so that we start drawing at the beginning of the row rather than where we left off.
  2. We to increase the value of y so that rows won't be drawn on top of each other.
  3. We need to reset numCols back to 0 so that it will keep the correct count when we restart drawing a row.
  4. We need to bump up numRows each time through.

Now all we need to do is to repeatedly execute the code for drawing a row by placing it inside an enclosing while loop. We've marked the new lines in the code below by marking them with "// new!".

    // draws a scarf with upper left at point of click
    public void onMouseClick( Location point )
    {
        double x = point.getX();
        double y = point.getY();    // x and y positions of the next "stitch"
        
        int numRows = 0;                 // new!
        int numCols = 0;
        
        while (numRows < SCARF_T) {      // new!
          while (numCols < SCARF_WIDTH) {
              new FramedOval(x, y, DIAMETER, DIAMETER, 
                             canvas).setColor(Color.green);
              x = x + X_DISP;
             numCols = numCols + 1;
          }
            
          x = point.getX();           // new!
          y = y + Y_DISP;             // new!
          numCols = 0;                // new!
          numRows = numRows + 1;      // new!
        }
    }

Exercises:

  1. Determine what would go wrong if each of the items listed above were omitted from the code.
  2. Modify the program so that the first row only has one circle, the second has 2, the third has 3, etc.

Suppose we wish to design a class to draw an American flag.

Demo: American Flag

A few things of note, some of which we have seen, others we have not:

  1. We use "++" to indicate that a variable's value should be incremented by one. Thus in drawStripes, each time through the loop, stripeNum++ increases the value of stripeNum by one.
  2. In general, x++; abbreviates x = x+1; if x is an int variable. A common mistake is to type x=x++;, which is wrong! This will end up not incrementing x, since x++ is a statement that increments x but returns its previous value! This means you increment x, then take the return value of x++ (which is the original x value) and assign that to x. So you haven't changed x after all!

  3. Private methods: The methods drawStripes and drawStars are called from inside the Flag constructor. They are not designed to be accessible from outside the class. They are designed only to be useful in breaking down the constructor into easier to understand pieces. drawStripes, is especially useful because it allows us to avoid duplicating code. Notice that it is used twice inside the constructor. Once to draw short stripes, and once to draw long stripes. Because we provide different parameters to it each time, it produces different results. If we did not use this private method, we would have to repeat the code in the method twice, once for each collection of values of the parameters.
  4. The drawStars method includes a nested while loop, with several items changing each time through the loop. In the outer while loop in drawStars, we must reinitialize both col and x each time through the loop.