Programming Exercises
For Chapter 7
THIS PAGE CONTAINS programming exercises based on
material from Chapter 7 of this on-line
Java textbook. Each exercise has a link to a discussion of one possible solution of that
exercise.
Exercise 7.1:
Exercise 5.2 involved a class,
StatCalc.java, that could compute
some statistics of a set of numbers. Write an applet that uses
the StatCalc class to compute and display statistics of
numbers entered by the user. The applet will have an instance
variable of type StatCalc that does the computations.
The applet should include a TextField
where the user enters a number. It should have four labels that
display four statistics for the numbers that have been entered:
the number of numbers, the sum, the mean, and the standard deviation.
Every time the user enters a new number, the statistics displayed
on the labels should change. The user enters a number by
typing it into the TextField and pressing return.
There should be a "Clear" button that clears out all the data.
This means creating a new StatCalc object and resetting
the displays on the labels. My applet also has an "Enter" button
that does the same thing as pressing the return key in the
TextField. (Recall that a TextField generates
an ActionEvent when the user presses return, so your applet
should register itself to listen for ActionEvents from the
TextField.) Here is my solution to this problem:
See the solution!
Exercise 7.2:
Write an applet with a TextArea where the use can enter
some text. The applet should have a button. When the user clicks
on the button, the applet should count the number of lines in the
user's input, the number of words in the user's input, and the
number of characters in the user's input. This information should
be displayed on three labels in the applet. Recall that if
textInput is a TextArea, then you can get the
contents of the TextArea by calling the function
textInput.getText(). This function returns a String
containing all the text from the TextArea. The number of
characters is just the length of this String. Lines
in the String are separated by the new line character,
'\n', so the number of lines is just the number of new line characters
in the String, plus one. Words are a little harder to
count. Exercise 3.4 has
some advice about finding the words in a String. Essentially,
you want to count the number of characters that are first characters
in words. Here is my applet:
See the solution!
Exercise 7.3:
The RGBColorChooser applet
lets the user set the red, green, and blue levels in a color by
manipulating scroll bars. Something like this could make a useful
custom component. Such a component could be included in a program to allow
the user to specify a drawing color, for example. Rewrite the
RGBColorChooser as a component. Make it a subclass of
Panel instead of Applet. Instead of doing the
initialization in an init() method, you'll have to do it
in a constructor. The component should have a method, getColor(),
that returns the color currently displayed on the component.
It should also have a method, setColor(Color c), to set
the color to a specified value. Both these methods would be useful
to a program that uses your component.
In order to write the setColor(Color c) method, you
need to know that if c is a variable of type Color,
then c.getRed() is a function that returns an integer
in the range 0 to 255 that gives the red level of the color.
Similarly, the functions c.getGreen() and c.getBlue()
return the blue and green components.
Test your component by
using it in a simple applet that sets the component to a random
color when the user clicks on a button, like this one:
See the solution!
Exercise 7.4:
In the Blackjack game BlackjackGUI.java
from Exercise 6.8,
the user can click on the "Hit", "Stand", and "NewGame" buttons
even when it doesn't make sense to do so. It would be better
if the buttons were disabled at the appropriate times. The
"New Game" button should be disabled when there is a game
in progress. The "Hit" and "Stand" buttons should be disabled
when there is not a game in progress. The instance variable
gameInProgress tells whether or not a game is in progress,
so you just have to make sure that the buttons are properly
enabled and disabled whenever this variable changes value.
Make this change in the Blackjack program. This applet uses
a canvas class, BlackjackCanvas, to represent the board.
You'll have to do most of your work in that class. In order to
manipulate the buttons, you'll need instance variables
to refer to the buttons. One problem you have to deal with
is that the buttons are used in both the applet class
and the canvas class.
I strongly advise using a subroutine to set the value of
the gameInProgress variable. Then the subroutine can take responsibility for
enabling and disabling the buttons.
Recall that if bttn is a variable of type
Button, then bttn.setEnabled(false)
disables the button and bttn.setEnabled(true) enables
the button.
See the solution!
[A working applet can be found here.]
Exercise 7.5:
Building on your solution to the preceding exercise, make it possible for the user
to place bets on the Blackjack game. When the applet starts, give the user $100.
Add a TextField to the strip of controls along the bottom of the applet.
The user can enter the bet in this TextField. When the game begins,
check the amount of the bet. You should do this when the game begins, not
when it ends, because several errors can occur: The contents of the TextField
might not be a legal number. The bet that the user places might be more money than
the user has, or it might be <= 0. You should detect these errors and show an
error message instead of starting the game. The user's bet should be an
integral number of dollars. You can convert the user's input into an integer, and
check for illegal, non-numeric input, with a try...catch statement of
the form
try {
betAmount = Integer.parseInt( betInput.getText() );
}
catch (NumberFormatException e) {
. . . // The input is not a number.
// Respond by showing an error message and
// exiting from the doNewGame() method.
}
It would be a good idea to make the TextField uneditable while the game
is in progress. If betInput is the TextField, you can make it
editable and uneditable by the user with the commands
betAmount.setEditable(true) and betAmount.setEditable(false).
In the paint() method, you should include commands to display the amount
of money that the user has left.
There is one other thing to think about: The applet should not start a new game
when it is first created. The user should have a chance to set a bet amount
before the game starts. In the constructor for the canvas class, you should not
call doNewGame(). You might want to start the game with the
message "Welcome to Blackjack".
See the solution!
[A working applet can be found here.]
Exercise 7.6:
The StopWatch component from Section 7.4
displays the text "Timing..." when the stop watch is running. It would
be nice if it displayed the elapsed time since the stop watch
was started. For that, you need to create a Thread. Add
a Thread to the original source code, StopWatch.java,
to display the elapsed time in seconds. Create the thread in
the mousePressed() routine when the timer is started.
Stop the thread in the mousePressed() routine when the timer
is stopped. The elapsed time won't be very accurate anyway, so just
show the integral number of seconds. You only need to set the text a
few times per second. In my run() method, I insert a delay of 100 milliseconds
after I set the text. Here is an applet that tests my solution
to this exercise:
See the solution!
Exercise 7.7:
The applet at the end of Section 7.8 shows
animations of moving symmetric patterns that look something like
the image in a kaleidascope. Symmetric patterns are pretty.
Make the SimplePaint3 applet do symmetric, kaleidascopic
patterns. As the user draws a figure, the applet should be able to
draw reflected versions of that figure to make symmetric pictures.
The applet will have several options for the type of symmetry
that is displayed. The user should be able to choose one of
four options from a Choice menu. Using the "No symmetry" option,
only the figure that the user draws is shown. Using "2-way symmetry",
the user's figure and its horizontal reflection are shown.
Using "4-way symmetry", the two vertical reflections are added.
Finally, using "8-way symmetry", the four diagonal reflections are
also added. Formulas for computing the reflections are given below.
The source code SimplePaint3.java
already has a putFigure() subroutine that draws all the figures.
You can add a putMultiFigure() routine to draw a figure and some or
all of its reflections. putMultiFigure can call the existing
putFigure to draw each figure. It decides which reflections to
draw based on the setting of the symmetry Choice menu. Where the mousePressed,
mouseDragged, and mouseReleased methods call
putFigure, they should call putMultiFigure instead.
If (x,y) is a point in a component that is width pixels wide
and height pixels high, then the reflections of this point are
obtained as follows:
The horizontal reflection is (width - x, y)
The two vertical reflections are (x, height - y) and (width - x, height - y)
To get the four diagonal reflections, first compute the diagonal reflection of (x,y) as
a = (int)( ((double)y / height) * width );
b = (int)( ((double)x / width) * height );
Then use the horizontal and vertical reflections of the point (a,b):
(a, b)
(width - a, b)
(a, height - b)
(width - a, height - b)
(The diagonal reflections are harder than they would be if the canvas were square.
Then the height would equal the width, and the reflection of (x,y) would just
be (y,x).)
To reflect a figure determined by two points, (x1,y1) and (x2,y2),
compute the reflections of both points to get the reflected figure.
This is really not so hard. The changes you have to make to the source
code are not as long as the explanation I have given here.
Here is my applet. Don't forget to try it with the symmetry Choice
menu set to "8-way Symmetry"!
See the solution!
Exercise 7.8:
Turn your applet from the previous exercise into a stand-alone
application that runs in a Frame. This is not an easy
exercise, since the material on frames in Section 7.7 is
sort of sketchy. The information is there if you read carefully.
(But I won't think too badly
of you if you just look at the solution.)
As another improvement, you can add an "Undo" button.
When the user clicks on the "Undo" button, the previous drawing operation will
be undone. This just means returning to the image as it was before the
drawing operation took place. This is easy to implement, as long
as we allow just one operation to be undone. When the off-screen canvas,
OSC, is created, make a second off-screen canvas, undoBuffer,
of the same size. Before starting any drawing operation,
copy the image from OSC to undoBuffer. You can do this with
the commands
Graphics undoGr = undoBuffer.getGraphics();
undoGr.drawImage(OSC, 0, 0, null);
When the user clicks "Undo", just swap the values of OSC
and undoBuffer and repaint. The previous image will appear
on the screen. Clicking on "Undo" again will "undo the undo".
Here is a button that
opens the paint program in its own window. (You don't have to
write an applet like this one. Just open the frame in the
program's main() routine.)
See the solution!