|
|
Laboratory 7
Lets go looping now, everybody is learning how
Week of 28 March, 2005
|
Objective
Being able to repeatedly execute statements of interest is a powerful
programming mechanism. In this laboratory you will gain practice with the Java
for statement.
Key Concepts
Getting Started
Using the procedures in the
previous laboratories, copy
the files
Count1.java,
Count2.java,
ForSum.java,
Fraction.java,
and Rectangles.java
for your manipulation. Three of these files (ForSum.java,
Fraction.java, and Rectangles.java) will need to be submitted.
For looping
A for statement has the following form:
for ( ForInit ; ForExpression ; ForUpdate )
Action
The execution of the ForInit initialization step begins the execution of
a for loop. The initialization step is executed only once,
regardless of how many times we iterate through the for loop.
The ForExpression is the test expression for the for loop. If the
test expression evaluates to true, the body of the loop (i.e., the
Action) is executed. After the body of the loop is executed (iterated), the
ForUpdate step is executed.
The test expression is then reevaluated. If the test expression again evaluates
to true, the body of the loop (i.e., the Action) is repeated. After the
body of the loop iterates, the ForUpdate step is executed again. This
process continues until the test expression evaluates to false.
- Examine program
Count1.java. What do you expect the values of variables
counter1 and counter2 to be?
- Compile and run the program. Did you get the same answers from your
manual calculations as you did from the computer program? If not, try to
determine why. If you cannot determine the reason, seek help from a lab assistant.
- Close Count1.java.
- Now consider the following program Count2.java,
which also contains two for loops. Unlike Count1.java, the two for loops do
not occur one after the other. In Count2.java, one loop is contained within
the action of the other loop. This placement is known as nesting. The nested
loop runs once per iteration of the outer loop. What you expect the
values of variables counter1 and counter2 to be?
- Compile and run the program. Did you get the same answers from your
manual calculations as you did from the computer program? If not, try to
determine why. Remember that the nesting of the inner loop causes a
multiplicative increase in the number of times its action is iterated. If
you cannot determine the reason, seek help from a lab assistant.
- Close Count2.java.
- Open the program ForSum.java. This program is
similar to program IntervalSum.java
of the previous laboratory. The program calculates the sum of integers from
a user-specified interval minNumber … maxNumber.
- Modify ForSum.java to instead use a for loop to accomplish its
purpose.
- The ForInit step of the loop should define an index variable
whose values over the course of the loop take on all of the values that
are to be summed.
- The ForExpression test expression of the loop should cause
the action to be executed if the index variable is sensible (i.e., its
value is one of the values to be summed).
- The Action of the loop should update the running total with
the current value of the index variable.
- The ForUpdate step should provide the index variable with
another value.
- Complete the program and compile it. Test the program to make sure it is
working correctly.
-
Submit program ForSum.java.
- Close ForSum.java.
Debugging
Improper initialization statements and termination conditions often are
causes of incorrect program behavior. The following example illustrates some
common mistakes.
- Open the file Fraction.java. Examine the
program to get a sense of what occurs during execution. The program attempts
to compute the value 1 by summing the fraction 1/n, n times. For example, if
n equals 3, then, ideally, the program should compute 1/3 + 1/3 + 1/3 = 1.
- The program contains an infinite loop. To terminate the program, if you
are running a console window, you may be able simply to close the shell
window. If not, you may need to enter an escape sequence such as CTRL-C or
CTRL-ALT-DEL. A help window may appear where you can terminate the errant
process. Sometimes as a result of the infinite loop, you are forced to
restart the machine without saving the program. In this case you will lose
unsaved modifications. As a precaution, you should always save a program
before running it.
- Compile and run the program using 2 as the input value and observe its
output, or in this case, lack of output.
- Modify the action of the loop by adding a System.out.println()
statement so that after updating total, the loop then displays the
current values of variables total, fraction, and loop.
System.out.println("total: " + total + " fraction: " + fraction +
" loopCounter: " + loopCounter);
- Also modify the loop by adding a stdin.nextLine() statement after
the println() statement. This statement causes the program to pause
between iterations – the program waits for the user to press the ENTER key.
stdin.nextLine();
- Monitor the output until you identify the problem.
- Correct the problem and again monitor the program to observe the
behavior of the variables.
- Rerun the program using 10 as the input value. Again step through the
program and observe the output. If necessary, terminate the program.
- The first time you ran the program, a mismatch occurred in the variable
types representing the fraction. That error is most likely not the problem
with this execution. Therefore, a different problem is occurring in the
loop. The problem now is that the fraction 1/10 is not represented perfectly
in Java. As a result, the exact sum is not calculated.
- Try to overcome this problem. If you can't figure it out, check out
this excerpt from the class slides.
-
Submit your corrected program Fraction.java.
- Close Fraction.java
Rectangle rendering
The next exercise shows how loops can accomplish a significant amount of work
using a small number of statements. You will develop a program Rectangles.java
to draw a geometric picture that should resemble the following figure. The
picture has five elements and each element is a series of concentric rectangles
that alternate in color. Note that it is not as important to understand
how Java creates the GUI window - instead, focus on the details of the for loop.
IMPORTANT: If you can't complete this section of the lab
during the lab session, that's fine. Do as much as you can during the
lab session, and turn in what you have completed (even if it is just
the skeleton code). If you spent all your time in lab session on the
other parts of this lab, then you can just turn in the skeleton code
for Rectangles.java.
- Open the file Rectangles.java. As written, the method displays only three of
the concentric elements. If you run this program the output will resemble the
following figure.
- The initial section of method main() first defines several constants.
final int SIZE = 400;
final int CENTER_X = SIZE/2;
final int CENTER_Y = SIZE/2;
final int NUMBER_ITERATIONS = 20;
final double SCALING = 0.8;
final int OFFSET = SIZE/4;
- The constant SIZE represents the width and height of the window that contains
the concentric rectangles. Constants CENTER_X and CENTER_Y represent the center
coordinates of the window. NUMBER_ITERATIONS represents the number of times the
rectangles will be drawn. SCALING represents the amount to reduce the rectangle
size on each iteration. OFFSET represents one-quarter of the length of a side of
the window. You can use OFFSET to help determine the centers of the concentric
rectangles that abut the sides of the window.
- We next define the display window.
JFrame window = new JFrame("Concentricity");
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setSize(SIZE, SIZE );
window.setVisible(true);
Graphics g = window.getGraphics();
- The concentric rectangles are displayed in JFrame window (whose title is
"Concentricity"). The width and height of window are set to the constant
SIZE.
The Graphics object g is the graphics context of window that we will use to
render the rectangles.
- Next the method defines the variable side. The variable side represents the
current size of a side of the rectangle being drawn. The first rectangles that
are displayed have sides whose lengths are equal to the constant SIZE.
int side = SIZE;
- A for loop occurs next in the method. The loop iterates NUMBER_ITERATIONS (20)
times. In each iteration, three rectangles are drawn — one rectangle for each of
the three concentric series being displayed. (Your task is to modify the code so
that it also displays the other two series.)
for (int i = 1; i <= NUMBER_ITERATIONS; i++)
- The first task of the for loop is to determine the color of the rectangles to be
drawn for the current iteration. If the value of i is even, the rectangle is
yellow; otherwise, the rectangle is blue. The color is set using the graphics
context g.
Color drawColor;
if (i % 2 == 0) {
drawColor = Color.YELLOW;
}
else {
drawColor = Color.BLUE;
}
g.setColor(drawColor);
- The rectangles are now drawn using the Graphics method fillRect().
- The first drawn rectangle is the rectangle in the upper-left corner of window.
Constants CENTER_X, CENTER_Y, and OFFSET determine the center of this rectangle.
By subtracting OFFSET from CENTER_X and from CENTER_Y, we can indicate a
rectangle closer to the origin with respect to both the x-axis and y-axis. The
coordinates of the center of this rectangle are (CENTER_X – OFFSET,
CENTER_Y –
OFFSET). However, method fillRect() draws a rectangle given the coordinates of
the top left corner of the rectangle. To find these coordinates, we subtract
half of the length of the rectangle (variable half) from the center coordinates
of the rectangle.
int half = side / 2;
int leftx = CENTER_X - OFFSET - half;
int topy = CENTER_Y - OFFSET - half;
g.fillRect(leftx, topy, side, side);
- The next drawn rectangle is the rectangle from the group in the lower right
corner of window. A positive OFFSET added to the window's center coordinates
gives the location of the center of this rectangle. Subtracting variable half
from these coordinates gives us the upper left corner of this rectangle.
int rightx = CENTER_X + OFFSET - half;
int bottomy = CENTER_Y + OFFSET - half;
g.fillRect(rightx, bottomy, side, side);
- The final rectangle is drawn at the center of window. Because it is at the
center, OFFSET is not needed.
int midx = CENTER_X - half;
int midy = CENTER_Y - half;
g.fillRect(midx, midy, side, side);
- As an after laboratory experiment, you may want to reorder the drawing of the
rectangles. Different orderings causes different displays.
- To prepare for the next iteration, side is updated. In the next iteration, the
program draws rectangles whose size is approximately 80 percent (the value of
SCALING) of the size of the current rectangles.
side = (int)(side * SCALING);
- Now modify the for loop body to construct and draw two more rectangles per
iteration. These rectangles should fill the corners of the window that have been
ignored temporarily. The rectangles can be displayed using two more g.fillRect()
invocations. The positions of these rectangles can be specified using existing
location variables (e.g., topy). The dimensions of the rectangles are the same as
the other rectangles (i.e., side by side).
-
Submit your completed program Rectangles.java.
- Close Rectangles.java.
- Why do the rectangles from one iteration remain on the screen for the next
iteration?
Finishing up
Copy any files you wish to keep to your own drive.
Delete all of the files you copied or created on the laboratory machine.