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
while and
for;
SimpleDate class.
Your instructor will tell you which of the proposed experiments you are to perform.
Prerequisite skills:
SimpleDate class created in
the previous laboratory session
Required code files:
DateTester.java
ForExamples.java
SimpleDate.java
(as extended in the previous laboratory session)
SimpleInput.java
SimpleOutput.java
WhileExamples.java
Optional applet files:
Bounce.java
ConfigurableGreeting.java
GridApplet.java
Rainbow.java
bounce.html
grid.html
rainbow.html
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.
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)
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.
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.
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.
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.
Name: ________________
ID:_______________
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.
Required files:
SimpleDate.java, as updated in the previous lab.
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:
for loopsRequired 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.)
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?
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.
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.
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.
daysUntilUsing 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.
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.
Having done Problems J5-A and J5-B, which one seems the more elegant way to solve the problem?
What looping mechanisms did you use in problems J5-A and J5-B? Why?
Write a program that reads in a sequence of grades, terminated by
-1 and prints out the average of the grades.
Write a program that reads in a sequence of grades, terminated by
-1 and prints out largest of the grades.
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.
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.
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.
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.
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.
[Front Door] [Introduction] [Code]
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