Experiments in Java


Session J5: Control Structures for Repetition

In this laboratory session, you will learn about control structures for repetition, which permit your Java programs to perform actions repeatedly. You will learn about these control structures as we further extend the Date object that represents dates. The goals of this laboratory are to

Your instructor will tell you which of the proposed experiments you are to perform.

Prerequisite skills:

Required code files:

Optional applet files:


Discussion

In the previous laboratory session, we developed a number of methods for the SimpleDate class, progressing from simple methods to more advanced methods. In this laboratory, we will continue with our exploration of the SimpleDate class. We will begin by looking at a dayOfYear method which determines which day of the year it is. From that method, we will develop a daysUntil method that determines the number of days until a particular date. Using that method, in the experiments you will develop a dayOfWeek method that determines the day of the week a date falls on.

Repetition

How do we determine what day of the year a particular date is? We can determine the number of days between the first day of the year and the first day of the month, and then add which day of the month it is. For example, consider February 3. The zeroth day of February is 31 days from the beginning of the year. February 3 comes three days later, so February 3 is 34 days from the beginning of the year.

Unfortunately, the computation for later months is not so easy. For example, how many days is August 1 from the beginning of the year? It may be possible to precompute all of those numbers, as in

  /**
   * Compute the position of this day within the current year.
   */
  public int dayOfYear() {
    int to_start_of_month;
    switch (this.month) {
      case 1:  // January
        to_start_of_month = 0;
        break;
      case 2:  // February
        to_start_of_month = 31;
        break;
      case 3:  // March
        to_start_of_month = 59; // We'll deal with leap years later in this function.
        break;
      ...
    } // switch(this.month)
    // Handle leap years
    if (this.isLeapYear() && this.month > 2) {
       to_start_of_month = to_start_of_month + 1;
    } // After February in a leap year
    // Add the days in this month
    return to_start_of_month + this.day;
  } // dayOfYear()

However, the work precomputing the position of the beginning of each month from the beginning of the year is painful and prone to simple errors in calculation if done by hand. Hence, we'd prefer to have the computer do such computation. How do we compute the number of days until the first of month m? We sum the number of days in each of the previous months. Algorithmically, we might write

// Compute the number of days until the start of month m
daysUntilStartOfMonth(m)
  sum the number of days in each month, p, that precedes m
  if it's a leap year and after February, add 1
  return the result

The sum command in that algorithm is vague and is not included in most programming languages. Hence, we must expand it to work out the details. How do we compute the sum? By explicitly adding the days in each prior month.

// Compute the number of days until the start of month m
daysUntilStartOfMonth(m)
  days = 0
  for each month, p, that precedes m
    add the number of days in month p to days
  end for
  if it's a leap year and after February, add 1 to days
  return days

The ``for each month'' is also vague. It may be better to make it explicit by using a counter.

// Compute the number of days until the start of month m
daysUntilStartOfMonth(m)
  days = 0
  p = 1
  while p < m
    add the number of days in month p to days
    add 1 to p
  end for
  if it's a leap year and after February, add 1 to days
  return days

Rewriting this in Java-like syntax, we get

  //**
   * Compute the number of days until the start of the month.
   */
  public int daysUntilStartOfMonth(int m) {
    int prev = 1; // A previous month
    int days = 0; // Total number of days
   
    // Sum the days in the previous months.  We assume that the
    // daysInMonth method handles leap years
    // correctly.
    while (prev < m) {
      days = days + this.daysInMonth(prev);
      prev = prev + 1;
    } // while

    // And that's it.
    return days;
  } // daysUntilStartOfMonth(int)

While loops

In fact, this is legal Java. Java provides a while statement with the following form.

while (test) {
  body
} // while

The test is executed. If it fails, the while loop terminates and control passes to the subsequent statement. If the test holds, then the statements in the body are executed. After the body is executed, the test is done again. The test and body are repeatedly executed until the test no longer holds.

Note that the test is done once per repetition, which means that the test need hold only at the beginning of the body. If, during the body, the test would no longer hold, execution of the body still continues until the end.

In Experiment J5.1 you will experiment with some basic looping examples.

Detour: Overloading revisited

Wait! Something seems wrong with the code above. It uses a daysInMonth(int) method, and you may recall that we designed daysInMonth to take no parameters. What do we do? Once again, this is an instance of overloading method names: providing multiple methods with the same name, but different types of parameters.

Using overloading, we might extend our old SimpleDate class with the new, parameterized daysInMonth. We can also have the old daysInMonth use the new one, as in

  /**
   * Compute the number of days in the current month.
   */
  public int daysInMonth() {
    return this.daysInMonth(this.month);
  } daysInMonth()

  /**
   * Compute the number of days in month m.
   */
  public int daysInMonth(int m) {
    switch (m) {
      case 1:
      case 3:
      ...
        return 31;
        break;
      case 2:
        if (this.isLeapYear()) {
          return 29;
        } // February in a leap year
        else {
          return 28;
        } // February, but not a leap year
        break;
      ...
    } // switch
  } // daysInMonth(int)

In Experiment J5.2 you will consider how to use loops to count days in the year.

for loops

Is the while loop the only looping mechanism that Java provides? No. Because so many algorithms naturally include a section that reads for every value of n between a and b do ... that Java includes a for control structure to make it more convenient to express such algorithms.

The for loop has the following form

for (initialization; test; increment) {
  body
} // for

In effect, this is a shorthand for the following while loop.

initialization;
while (test) {
  body;
  increment;
} // while

That is, a for loop begins by executing the initialization portion. Traditionally, this sets the initial value for a counter variable. Next, it executes the test. If the test fails, the loop terminates and control moves on to the next statement. If the test succeeds, the body is executed. After the body is done, the increment is executed. The test is done again, and the cyclic process continues.

For example, we might rewrite our daysUntilStartOfMonth method as

  //**
   * Compute the number of days until the start of the month.
   */
  public int daysUntilStartOfMonth(int m) {
    int prev = 1; // A previous month
    int days = 0; // Total number of days
   
    // Sum the days in the previous months
    for (prev = 1; prev < m; prev = prev + 1) {
      days = days + this.daysInMonth(prev);
    } // for
    
    // Deal with leap years
    if (this.isLeapYear() && m > 2) {
       days = days + 1;
    } // After February in a leap year

    // And that's it.
    return days;
  } // daysUntilStartOfMonth(int)

In Experiment J5.3 you will consider some simple examples of for loops.

Detour: Arithmetic shorthand

As you read other people's Java code (or C code or C++ code or ...), you will find many shorthand expressions for common arithmetic expressions. For example, it is so typical to add one to a variable that Java includes a ++ operator that does just that. In particular,

    ++i;

is the same as

    i = i + 1;

Hence, you will often see for loops that look like

    for (i = 0; i < n; ++i) 

The prefix ++ (also called preincrement) differs from the longer form in that it can be more easily used as part of larger expressions. For example,

    j = ++i + 3; 

represents ``Add 1 to i. Add 3 to the updated i, and store the result in j.''

There is also a postfix ++ (also called postincrement) that adds 1 to the argument, but returns the old value. For example,

    j = i++ + 3; 

represents ``Add 1 to i; add 3 to the old value of i; store the result in j''.

As you might guess, there are also prefix and postfix -- operators (predecrement and postdecrement), with the intended meaning of decrementing the corresponding variable.

Finally, Java also provides a += assignment which has the affect of adding the right-hand-side to the left-hand-side. For example,

k += 5;

represents ``Add 5 to k''.

In Experiment J5.4 you will consider Java's various arithmetic shorthands.

Loops and applets

This section is optional and is intended for classes emphasizing applets or pursuing a simultaneous discussion of applications and applets.

Loops have many applications for applets, particularly with regards to drawing regular and repetitious figures, such as sequences of images. In Experiment J5.5, you will use for loops to create a rainbow text effect. In Experiment J5.6, you will track down errors in an applet designed to draw a regular grid using a for loop.

In Experiment J5.7, you will attempt a more complicated task: showing the positions of a bouncing ball. In order to make the ball bounce, you need to be able to determine the area available to the applet.

You may have noted that the dimensions (width and height) of the area reserved for an applet are set within the HTML files that loads the applet and not within the applet itself. Clearly, it is possible to load the same applet with different dimensions and different pages may therefore choose different dimensions for the same applet. For many applets, it becomes important for the applet designer to be able to determine these dimensions. This is particularly true of our bouncing ball applet, in which the ball must change direction

Fortunately, Java provides a mechanism for the applet author to determine the dimensions given for the applet. You can call this.getSize() to obtain a java.awt.Dimension object. You can then get the width of that object by referring to its width and height fields.

For example, you might write the following to set the right and bottom edges of the area allocated to the applet. Note that since the area begins at (0,0), the width of the applet gives the horizontal offset of the right edge, and the height of the applet gives the vertical offset of the bottom edge.

    int right;  // The right edge of the area allocated to the applet.
    int bottom; // The bottom edge of the area allocated to the applet.
    Dimension dim = this.getSize();
    right = dim.width;
    bottom = dim.height;

Now, how do you make the ball bounce? We'll explore that issue in Experiment J5.7.


Experiments

Name: ________________
ID:_______________

Experiment J5.1: Simple loops

Required files:


/**
 * A collection of methods that use Java's looping mechanisms.
 *
 * @author Samuel A. Rebelsky
 * @version 1.0 of August 1998
 */
public class WhileExamples {
  /**
   * Print the numbers from 1 to n
   */
  public void countTo(int n, SimpleOutput out) {
    int i = 1;
    while (i < n) {
      out.println(i);
      i = i + 1;
    } // while
  } // countTo(int n, SimpleOutput out)

  /**
   * Keep reading passwords until you read the supplied password.
   */
  public void readPass(SimpleInput in, 
                       SimpleOutput out, 
                       String pass) {
    String name = "";
    while (!name.equals(pass)) {
      out.print("Enter the password: ");
      name = in.readString();
      // If the password was entered correctly, the loop
      // should terminate.
      out.println("'" + name + "' was not a valid password.");
    } // while
  } // readPass(SimpleInput, SimpleOutput, pass)
} // class WhileExamples


Step 1. Make a copy of WhileExamples.java. That class includes a countTo method. What should this method do (in general)? What should the method do if called with a value of 10 for n. Do you think that countTo will work correctly? Why or why not?


 
 
 

Step 2. Write a class, TestLoops, that includes a main method that calls countTo with 10 as the value for n. Record the results. Were these what you expected?


 
 
 

Step 3. If countTo did not have the correct results, explain why not. If countTo did have the correct results, can you envision any simple errors one might have made?


 
 
 

Step 4. Add a count(int from, int to, SimpleOutput out) method to WhileExamples. This method should count all the numbers beginning with from and ending with to. Test your method. Enter the code for your method here.


 
 
 
 
 
 
 
 
 
 
 
 
 
 

Step 5. Read the code for the readPass method from WhileExamples.java. This code has a small logical problem. What do you think the problem is?


 
 
 

Step 6. Update your main method to call readPass with a password of Hello. Run your program using passwords of hi, hello, and Hello. Record the results.


 
 
 

Step 7. Based on those results, what is the logical problem in readPass?


 
 
 

Step 8. Update readPass so that it gives correct output. Summarize the changes.


 
 
 
 
 
 

Experiment J5.2: Counting the day of the year

Required files:

Step 1. Add a daysInMonth(int m) method to SimpleDate. Test your code. Enter your code for the method here.


 
 
 
 
 
 
 
 
 
 
 
 
 
 

Step 2. You may have observed that both of the versions of daysInMonth assume that you want to use the current year. Add a daysInMonth method that takes both month and year as parameters. Test your code. Enter your code for the method here.


 
 
 
 
 
 
 
 
 
 
 
 
 
 

Step 3. Update the original daysInMonth and the daysInMonth you created in Step 1 to use the daysInMonth you created in Step 2. Enter the revised code for your methods here.


 
 
 
 
 
 
 
 
 
 
 
 
 
 

Step 4. Using the ideas from above, add a daysUntilStartOfMonth method for the SimpleDate class. This method should compute the number of days until the beginning of the current month. Test your code. Enter your code here.


 
 
 
 
 
 
 
 
 
 
 
 
 
 

Step 5. Write a program that computes how many days there are before the start of December in a non-leap year. You should use the SimpleDate class and the corresponding methods you developed earlier.


 
 
 

Step 6. Using the daysUntilStartOfMonth, add a dayOfYear method to the SimpleDate class. This method should compute the number of days from the beginning of the year until the current date. Test your code and enter it here.


 
 
 
 
 
 
 
 
 
 
 
 
 
 

Step 7. Using the updated SimpleDate class, determine on which day of the year the following dates fall:

Experiment J5.3: Simple for loops

Required code files:


/**
 * Simple examples of Java's for loops.
 *
 * @author Samuel A. Rebelsky
 * @version 1.0 of September 1998
 */
public class ForExamples {

  /**
   * Sum the squares of the numbers from 1 to n.
   */
  public int sumSquares(int n) {
    int sum = 0;  // The sum of the numbers
    int i;        // A counter for the loop

    for (i = 0; i <= n; ++i) {
      sum = sum + i*i;
    }

    return sum;
  } // sumSquares(int)

} // class ForExamples
 


Step 1. Read the code for sumSquares from the class ForExamples. What does the method do? Do you expect that it will work correctly? Why or why not?


 
 
 
 
 
 

Step 2. Using ForExamples, write a program that reads in an integer, n, and prints the sum of squares from 1 to N. For example, if you enter 3, it should compute 1*1 + 2*2 + 3*3 = 14 and print out 14. Enter your code for the program here.


 
 
 
 
 
 
 
 
 
 
 
 
 
 

Step 3. Run your program on inputs of 1, 3, 5, 10, 20, 0, and -3. Record your results.


 
 
 
 
 
 

Step 4. Add a sumCubes method to ForExamples. This method should compute the sum of cubes of integers from 1 to n. Enter your code for the method here.


 
 
 
 
 
 
 
 
 
 
 
 
 
 

Step 5. Run your program on inputs of 1, 3, 5, 10, 20, 0, and -3. Record your results.


 
 
 
 
 
 

Step 6. Add a sumTo method to ForExamples. This method should compute the sum of the integers from 1 to n. Enter your code for the method here.


 
 
 
 
 
 
 
 
 
 
 
 
 
 

Step 7. Did you use a for loop for step 6? If so, see if you can rewrite it without using a for loop, while loop, or recursive function calls. (The sum of 1+2+...+N is a well-known formula; you should already know it. If not, you should find it.)


 
 
 
 
 
 
 
 
 
 
 
 
 
 

Experiment J5.4: Arithmetic shorthand

Step 1. Write a program that includes the following two lines. Print out the values of i and j after the two statements. (Note that i and j must be integer variables.) Record the values.

i = 2;
j = ++i + 3;


 
 
 

Step 2. Write a program that includes the following two lines. Print out the values of i and j after the two statements. Record the values.

i = 2;
j = i++ + 3;


 
 
 

Step 3. Did you get the same values in steps 1 and 2? Why or why not?


 
 
 

Step 4. Write a program that includes the following two lines. Print out the values of i and j after the two statements. Record the values.

i = 2;
j = i-- + 3;

Step 5. Write a program that includes the following two lines. Print out the values of i and j after the two statements. Record the values.

i = 2;
j = i-- + 3;


 
 
 

Step 6. What do you think the value of i and j will be after the following lines are executed. Why?

i = 2;
j = i++ - i++;


 
 
 
 
 
 

Step 7. Execute the lines from the previous step and record the results. What do they suggest?


 
 
 
 
 
 

Experiment J5.5: Rainbow text

Optional applet experiment

Required files:

Step 1. Make copies of ConfigurableGreeting.java, Rainbow.java, and rainbow.html. Compare ConfigurableGreeting.java (which you've used in previous experiments) and Rainbow.java. How are they similar? How are they different?


 
 
 
 
 
 

Step 2. Why do you think Rainbow.java includes the variables changeRed, changeBlue, and changeGreen?


 
 
 

Step 3. Why do you think Rainbow.java includes the variables horiz and vert?


 
 
 

Step 4. Compile Rainbow.java and load the applet from rainbow.html. Describe the output from the applet.


 
 
 

Step 5. The stated goal of Rainbow is to draw text in a rainbow. Rainbox, however, does not not appear to do so. Rather, it draws the text in a single color. To draw the text in a rainbow of colors, we'll need to draw the text multiple times, changing the color and position each time. We'll start by adding a for loop. Replace the lines that read

    paintBrush.setColor(new Color(redPart, greenPart, bluePart));
    paintBrush.drawString(message, horiz, vert);

with the following for loop.

    // Repeatedly draw the message in different colors and positions.
    for (int step = 1; step <= steps; step = step + 1) {
      // Draw the message in the current color at the current position.
      paintBrush.setColor(new Color(redPart, greenPart, bluePart));
      paintBrush.drawString(message, horiz, vert);
    } // for(step)

What effect do you expect the change to have?


 
 
 

Confirm your answer by recompiling Rainbow and loading the applet from rainbow.html. You may also want to consult the notes on this step.

Step 6. We will now update the applet so that the message is printed in a different space each time. Add the following lines to the end of the for loop that you added in the previous step.

      // Update the position.
      horiz = horiz + 1;
      vert = vert + 2;

What effect do you expect the change to have?


 
 
 

Confirm your answer by recompiling Rainbow and loading the applet from rainbow.html.

Step 7. As you may have noted, the result of the previous step is a somewhat smudged version of the message, which makes it hard to read. We can make it somewhat clearer by writing the message in black at the end. Add the following lines after the for loop.

    // Draw the message a final time.
    paintBrush.setColor(Color.black);
    paintBrush.drawString(message, horiz, vert);

Test the appearance using both white and black. Which do you prefer?


 
 
 

Step 8. We are now ready to start changing the color (something we would hope to happen in a rainbow). In step 6, we changed horiz and vert. In this step, we'll change redPart, greenPart, and bluePart. Choose an appropriate way to change each of the three (hint: use changeRed, changeBlue, and changeGreen). Verify that your change works by recompiling Rainbow and loading the applet from rainbow.html. Summarize your changes here.


 
 
 
 
 
 

After you have recorded your answer, you may wish to consult the notes on this step for the recommended changes.

Step 9. Currently, we have the for loop draw the message twenty times. What do you expect to happen if we draw the message forty times?


 
 
 

Confirm your answer by updating rainbow.html and then loading the applet from rainbow.html. You may also wish to consult the notes on this step.

Step 10. As you may have noted, the difficulty with taking too many steps is that the color components eventually fall outside of the acceptable range (values between 0 and 255). We can account for this problem by checking the value and, if it's outside the range, either (1) stopping at the maximum/minimum value or (2) changing the way we change the color. We'll use the second technique.

Add the following lines to the for loop, after the change to the color. (Also add corresponding lines for blue and green.)

      // Handle colors out of the range 0..255.
      if (redPart < 0) { 
        redPart = 0;
        changeRed = Math.abs(changeRed);
      }
      if (redPart > 255) {
        redPart = 255;
        changeRed = -(Math.abs(changeRed));
      }

Recompile Rainbow and load the applet from rainbow.html. In your own words, explain what these new lines do.


 
 
 

Step 11. At present, our rainbow appears as a diagonal line. We might prefer it to appear as a curve (perhaps even in something resembling a rainbow shape). How might we make the rainbow curve?


 
 
 

Step 12. Delete the lines that read

      horiz = horiz + 1;
      vert = vert + 2;

Insert the following lines before the call to drawString in the for loop in the paint method in Rainbow.

      // Determine the position.
      horiz = 2*step;
      int tmp = step-steps/2;
      vert = 20+100*4*(tmp*tmp)/(steps*steps);

What do you think these lines do?


 
 
 

Confirm your answer by updating rainbow.html and then loading the applet from rainbow.html. You may wish to use 100 steps. You may also wish to consult the notes on this step.

Experiment J5.6: A grid applet

Optional applet experiment

Required files:

Step 1. In many graphics applications, it is useful to be able to create a regularly spaced grid of points. The applet given by GridApplet.java is intended to do just that. Make copies of GridApplet.java and grid.html. Compile GridApplet and load the applet from grid.html. Describe the output.


 
 
 

Step 2. Describe, in your own words, how you might write an applet to create that grid. Do not read the code for GridApplet.


 
 
 
 
 
 

After recording your answer, you may wish to consult the notes on this step.

Step 3. Consider the code for GridApplet. That code contains a number of logical errors. Identify as many as you can. List them here.


 
 
 
 
 
 

Step 4. Update grid.html so that it uses eight rows and eight columns. Do not change GridApplet. Reload the applet using the modified grid.html. Does the grid change? Why or why not?


 
 
 

Step 5. One reason you may have speculated that the grid doesn't change is that the applet never consults the HTML file. Add appropriate Java code so that GridApplet reads the number of columns and rows from the HTML file. You should be able to develop that code on your own. However, if you need help, you may consult the notes on this step. Summarize the new code here.


 
 
 
 
 
 

Step 6. Recompile GridApplet and load the applet using grid.html. Do you get the appropriate number of rows and columns? Why or why not?


 
 
 

After recording your answer, you may wish to consult the notes on this step.

Step 7. Update the for loops to use the appropriate variables. More particularly, replace the line that reads

    for (int row = 1; row < 4; row=row+1) {

with

    for (int row = 1; row < rows; row=row+1) {

Replace the line that reads

      for (int col = 1; col < 5; col=col+1) {

with

      for (int col = 1; col < cols; col=col+1) {

Recompile GridApplet and load the applet using grid.html. Do you get the appropriate number of rows and columns? Why or why not?


 
 
 

After recording your answer, you may wish to consult the notes on this step.

Step 8. Update the for loops to use appropriate termination conditions. More particularly, replace the line that reads

    for (int row = 1; row < rows; row=row+1) {

with

    for (int row = 1; row <= rows; row=row+1) {

Replace the line that reads

      for (int col = 1; col < cols; col=col+1) {

with

      for (int col = 1; col <= cols; col=col+1) {

Recompile GridApplet and load the applet using grid.html. Do you get the appropriate number of rows and columns? Why or why not?


 
 
 

Step 9. Update grid.html so that it draws ten rows and five columns. Reload the applet using the modified grid.html. Do you get the appropriate number of rows and columns? Why or why not?


 
 
 

After recording your answer, you may wish to consult the notes on this step.

Step 10. As you may have noted, rows and columns seem to be reversed. Often problems like this happen because programmers nest their loops incorrectly. Update your code so that the columns loop is the outer loop and the rows loop is the inner loop. For example, you might write

    // For each column ...
    for (int col = 1; col <= cols; col=col+1) {
      // Step through the rows, drawing the grid point at
      // the current row/column.
      for (int row = 1; row <= rows; row=row+1) {
        ...
      } // for each row
    } // for each column

Do you think this will fix the problem? Why or why not?


 
 
 

Confirm your answer by recompiling GridApplet and reloading the applet with grid.html.

Step 11. It seems that the problem does not have to do with the nesting of the loops. What is the problem? If we look closely, we may notice that it has to do with the fillOval command. That command makes the vertical position (the first coordinate) dependent on the row, and the horizontal position (the second coordinate) dependent on the column. However, all points in the same row should have the same vertical position, and all points in the same column should have the same horizontal position. Replace the line that reads

        paintBrush.fillOval(row*spacing, col*spacing, 3, 3);

with one that reads

        paintBrush.fillOval(col*spacing, row*spacing, 3, 3);

Confirm that the applet now works correctly.

Step 12. After all that hard work, it's time for a little bit of fun. Add the following line before the line you just changed.

        paintBrush.setColor(new Color(row*255/rows,128,col*255/cols));

What effect do you expect this new line to have?


 
 
 

Confirm your answer by recompiling GridApplet and reloading the applet with grid.html.

Experiment J5.7: A bouncing ball

Required files:

Step 1. Make copies of Bounce.java and bounce.html. Compile Bounce and load the applet from bounce.html. Describe the output of the applet.


 
 
 

Step 2. Update bounce.html to change the horizontal velocity to 9 and the acceleration to 2. Reload the applet from the modified bounce.html. What effect do the changes have?


 
 
 

Step 3. Update bounce.html to change the number of repetitions to 10. Reload the applet from the modified bounce.html. What effect does the change have?


 
 
 

When you are done, restore the number of repetitions to 100.

Step 4. Read the code for Bounce.java. In your own words, describe what it does.


 
 
 
 
 
 

Step 5. Add the following lines to the paint method of Bounce, just before the call to fillOval.

      int tmp = 200-200*step/repetitions;
      paintBrush.setColor(new Color(tmp,tmp,tmp));

What effect do you expect these new lines to have?


 
 
 

Confirm your answer by recompiling Bounce and loading the applet from bounce.html.

Step 6. As you may have noted, the ball does not yet bounce. In your own words, suggest how we might make the ball bounce.


 
 
 

Step 7. If you ask a physicist, you may learn that when a ball bounces, its velocity changes from downward to upward. You can simulate this change by reversing the sign on horizVelocity. When do you do what? When the ball reaches the bottom of the screen. Replace the lines that read

      // Update the speed.
      vertVelocity = vertVelocity + acceleration;

with the following

      // Update the speed.
      if (vert > bottom) {
        vertVelocity = -Math.abs(vertVelocity);
      }
      vertVelocity = vertVelocity + acceleration;

What effect do you expect these new lines to have?


 
 
 

Confirm your answer by recompiling Bounce and loading the applet from bounce.html.

Step 8. Explain why we used

        vertVelocity = -Math.abs(vertVelocity);

instead of

        vertVelocity = -vertVelocity;


 
 
 

After recording your answer, you may wish to consult the notes on this step.

Step 9. As you may have observed, it is now possible for the ball to exit the right edge of the screen. Update your applet so that the ball bounces at both the right and left edges of the screen. Summarize your changes here.


 
 
 
 
 
 

After recording your answer, you may wish to consult the notes on this step.


Post-Laboratory Problems

Problem J5-A: daysUntil

Using Java's two primary looping mechanisms, we can investigate a more complicated issue: How do we determine the number of days between two dates? More precisely, how do we write the following method?

  /**
   * Determine the number of days from the current day until
   * the event.  Note that the event must occur after the
   * current day.
   */
  public int daysUntil(Date event) {
    ...
  } // daysUntil(Date)

We might employ a number of strategies to answer this question. We might determine the number of days each date falls from a set date (e.g., January 1, 1970) and then subtract the two. We might also use a strategy like the one we used for determining the number of days until the start of the month. That is, rather than counting up days in each month, we might count up the days in each year, starting with the first year and ending with the final year.

We recommend that you try both.

Add a daysSinceDayZero method to the SimpleDate class. This method should compute the number of days since some designated day zero (you can determine what that date is) until the current date (i.e., the one represented by this).

Write a daysUntil method that uses daysSinceDayZero to compute the number of days until another day.

Problem J5-B: daysSince

Write a daysSince method that computes the number of days since another date. Don't use daysSinceDayZero or daysUntil. You will probably need to count up the days in each year, as described earlier.

Problem J5-C: Reflection

Having done Problems J5-A and J5-B, which one seems the more elegant way to solve the problem?

Problem J5-D: Loop mechanisms

What looping mechanisms did you use in problems J5-A and J5-B? Why?

Problem J5-E: Grade averaging

Write a program that reads in a sequence of grades, terminated by -1 and prints out the average of the grades.

Problem J5-F: Maximum grade

Write a program that reads in a sequence of grades, terminated by -1 and prints out largest of the grades.

Problem J5-G: Revising the rainbow's shape

In Experiment J5.5, we created a simple rainbow from a message. We saw how to make that rainbow appear as a diagonal line, and as a simple curve. Find a few other interesting curves for the rainbow. Make it possible for the HTML page to select what curve to use.

Problem J5-H: Revising the rainbow

One of the difficulties of the rainbow from Experiment J5.5 is that the progression of colors was not particularly sophisticated. This is because it's difficult to switch between our normal sense of a rainbow (which is based on wavelengths) and the RGB color model. Java's java.awt.Color class also supports the hue, saturation, and brightness (HSB) model. Read the documentation on java.awt.Color and the corresponding getHSBColor method, and use this method to improve the appearance of the rainbow.

Problem J5-I: A complete grid

In Experiment J5.6, we created a grid of points whose spacing and number of columns and rows were specified by the corresponding HTML page. However, one might instead prefer to have the number of columns and rows determined by the area given to the applet, along with the spacing. Write a new grid applet that fills the applet's area with a regularly spaced grid of points.

Problem J5-J: Improving the bouncing simulation

You may have observed that there are some problems with the bouncing simulation from Experiment J5.7. In particular, even the the bouncing is supposed to be 100 percent elastic, the ball seems to bounce lower and lower at each step. Why is this? Because our code does not appropriately account for the part of the ``step'' in which the ball bounces. In particular, it effectively treats a ball that bounces early in the step (i.e., if it started quite near the floor) the same as one that bounces later in the step (i.e., that fell most of the way before bouncing). Improve the simulation to handle that issue. While doing so, make sure that the ball does not fall below the bottom of the screen.

After making that improvement, consider how you might take elasticity more explicitly into account.


Notes

Experiment J5.5, Step 5. The applet now draws the given message twenty times. However, since we don't change the value of any of the variables, the message appears twenty times in the same place. Hence, the output of the applet will be the same.

Experiment J5.5, Step 8. To support more variation in the applet, use something like the following when updating the colors

      // Update the colors.
      redPart = redPart + changeRed;
      greenPart = greenPart + changeGreen;
      bluePart = bluePart + changeBlue;

These lines belong within the for loop.

Experiment J5.5, Step 9. Eventually, one or more of the components (redPart, greenPart, or bluePart) will exceed 255 (or fall below 0). The java.awt.Color class does not permit this, and will report an error to the browser or applet viewer. Think about how you might deal with this problem.

Experiment J5.5, Step 12. The seemingly complicated math is not that complicated. Basically, we're drawing part of a parabola. As you may recall, a parabola is given by a quadratic equation. In this case, we make the vertical component depend on the square of the step number (tmp*tmp) and the horizontal component linear in the step number. We make the peak of the parabola at the middle by subtracting steps/2 from the step before squaring. (Hence, that value will be zero when we are at the middle of our steps.) We divide by steps*steps and multiply by 4 to scale the value (the largest value should be approximately (steps/2)*(steps/2), so we divide by that value). We multiply by 100 so that we end up with a value between 0 and 100 (more or less).

You may wish to try variants of these values to see what effects they have.

Experiment J5.6, Step 2. A typical strategy will involve nested for loops. We step through the rows (using a for loop). Within each row, we step through the columns (again, using a for loop). For example,

    // For each row ...
    for (int row = 1; row <= rows; row = row + 1) {
      // Draw all the grid points on this row.
      // For each column ...
      for (int col = 1; col <= cols; col = col + 1) {
        // Draw the grid point for the given row/column.
        ...
      } // for each column
    } // for each row

Experiment J5.6, Step 5. Your new code should resemble the following.

    // Read the parameters from the HTML page.
    String rowString = getParameter("rows");
    String colString = getParameter("columns");
    String spacingString = getParameter("spacing");
    try { rows = Integer.parseInt(rowString); }
    catch (Exception e) { rows = 1; }
    try { cols = Integer.parseInt(colString); }
    catch (Exception e) { cols = 1; }
    try { spacing = Integer.parseInt(spacingString); }
    catch (Exception e) { spacing = 10; }

Experiment J5.6, Step 6. Although we are reading the number of rows and columns, we are not using them within our code. More precisely, the for loops use specified ending values, rather than the variables rows and cols.

Experiment J5.6, Step 7. As you may have noted if you looked closely, we have seven rows and seven columns. What might be wrong? It could be that the first row and the first column fall outside the applet's window. It could be that we're counting wrong. You might verify that the first is not the problem by using a drawing command that you are sure will place the points within the screen (e.g., by adding 10 to horizontal and vertical positions). In fact, because our for loops use < rather than <=, they stop one step too soon.

Experiment J5.6, Step 9. It appears that we've drawn five rows and ten columns, rather than ten rows and five columns. Obviously, we've gotten something backwards.

Experiment J5.7, Step 8. Because our simulation currently allows the ball to go below the bottom of the area, it is possible that it remains below the bottom, even after it starts upward. We want to make sure that the velocity is always negative (upwards) when the ball is below the bottom. In a post-laboratory problem, you will have the opportunity to consider how to prevent the ball from going below the bottom.

Experiment J5.7, Step 9. When the ball reaches the right edge, it should start moving towards the left (a negative horizontal velocity). Hence, we use

      if (horiz > right) {
        horizVelocity = -Math.abs(horizVelocity);
      }

When the ball reaches the left edge, it should start moving toward the right (a positive horizontal velocity). Hence, we use

      if (horiz < left) {
        horizVelocity = Math.abs(horizVelocity);
      }

Your answer may differ slightly.


Copyright (c) 1998 Samuel A. Rebelsky. All rights reserved.

Source text last modified Wed Oct 6 12:41:07 1999.

This page generated on Tue Oct 26 15:39:32 1999 by Siteweaver.

Contact our webmaster at rebelsky@math.grin.edu