At this point, you have more than enough Java programming skills to be a danger
to yourself and others. You can write programs for the World Wide Web and programs
to run locally on your computer. The next several hours will test your skills as
you apply them to some practical examples of programming.
The program you'll be writing during this hour and the next hour will serve two
purposes. First, it will give you a chance to create an object and use it in another
program. Second, you'll be building gambling skills that will hold you in good stead
at the next illicit gambling den you visit. During this hour, you'll create a Die
object and test it out with a simple Java program. Once it works, you'll be using
the Die object in a Craps applet during Chapter 22, "Writing
a Game for the Web."
The following topics will be covered during this hour:
How to play craps
Creating an object to handle a task
Generating random numbers for dice rolls
Drawing dice using polygons
Determining what to display using if-then blocks
Using methods of the Math class
Storing values in the variables of a class
Using arguments with methods
Setting up variables in a constructor method
Craps
Everyone has different recollections of childhood, but who doesn't have memories
of skipping school, staying out all night, and blowing all your lunch money at the
craps table with some of the neighborhood drug dealers? Most of us don't have these
memories, unfortunately, because of restrictive parents and their crazy notion that
a good education and sleep were important for their kids.
Luckily, you can simulate a little of that gambling den experience by playing
a craps game on your computer. Craps, in case you're particularly sheltered, is a
game involving two six-sided dice. The goal is to roll a winning number with the
dice before you roll a losing number. Craps has some complicated rules for gambling,
but the program you'll write during this hour will focus on dice rolling, winning
numbers, and losing numbers. The number of winning rolls and losing rolls will be
totaled up as you play, giving you an idea of how often a craps player rolls a winning
pair of dice.
When a player rolls the dice for the first time, any combination of the two dice
that adds up to 7 or 11 is a winner. Any dice total that equals 2, 3, or 12 is an
immediate loser and is called craps, as in "Oh, crap, I just lost the money
I needed for liposuction surgery!" If the first roll is not an immediate winner
or a loser, the total of the dice becomes known as the point. For all successive
rolls, the player will win a game if the point is rolled again. However, if a 7 is
rolled before the point is rolled, the player craps out.
The following is a sample game rolled by motion picture star Pia Zadora:
1. Pia rolls a 5 and a 6, adding up to 11. She wins the game instantly.
That example wasn't long enough for illustrative purposes, so here's another game
from Ms. Zadora:
1. Pia rolls a 6 and a 2. This roll makes 8 the point. On all successive
rolls, an 8 will win, and a 7 will lose.
2. Pia rolls a 4 and a 2, adding up to 6. She must roll again.
3. Pia rolls snake eyes--2. She didn't roll the point (8), so she has to roll
again.
4. Pia rolls a 3 and 4 (for a total of 7), crapping out.
Now that you know how craps works, it's time to teach the game to your computer.
When you're done, you'll be writing a Craps applet that you can put on a
World Wide Web page.
Organizing the Program
Before you tackle any programming project, spend some time thinking about how
it should be implemented. Planning ahead can prevent you from doing work in the program
that has to be redone later because it wasn't done correctly. It also can make the
finished program easier to understand and easier to maintain later on.
If you're particularly organized, you might want to create a flowchart that illustrates
the way the program will function. Flowcharts are an effective way to demonstrate
the logic a computer should follow as it handles a program. Even if you don't create
flowcharts, you should make a list of the things your program must do. Think about
each task that must be handled for the program to work, and don't worry about putting
them in any order.
For example, the Craps applet includes the following list of tasks:
Roll two dice and add them up
Figure out if the dice total is a winner or a loser
Draw the dice on the screen
Keep track of the point value if the first roll doesn't win or lose
Count the number of wins and losses
Create a way for the player to roll the dice
As you can see, almost all aspects of the Craps applet will involve the
dice. During Chapter 10, "Creating Your First Object," you saw how a computer
program can be thought of as a group of objects that work together to accomplish
a task. One way to conceptualize the Craps program is to create an object
that represents a six-sided die. If you can create a Die class that can
roll itself, draw itself, and keep track of its own value, most of the work of a
Craps applet will be done. An advantage to creating a separate Die
class of objects is that you can use this class in any program you write that involves
dice. The only things left for the applet to do are to create two Die objects,
ask them to roll themselves, take user input, and keep score.
Creating a Die Class
The Die class of objects that you will create must handle the following
tasks:
Set up an initial value for itself when it is created
Roll itself
Keep track of its own value
Draw itself
Using your word processor, create a new file named Die.java. Each section
of the Die class will be described as you enter the text. Begin with the
following line:
import java.awt.*;
This line makes Java's Abstract Windowing Toolkit classes available for use in
the Die class.
Throughout this section, Die is described as a class of objects rather
than as a program. Class, object, and program are largely synonymous in Java, but
it's helpful to think of them in the following way: A program is a set of computer
instructions that handle a task. Objects are used by a program to accomplish its
work. A class is the template that determines how an object is created and what it
can do.
After adding a blank line, enter the following statements:
public class Die {
public int value;
The first line begins the Die class and indicates that the name of the
source file should be Die.java. Die does not use the extends
statement along with public class, so it does not inherit any capabilities
from other objects. It's a unique class of objects.
The second line creates an integer variable called value. This variable
will be used to store the value of the die after it is rolled. Because the object
is a six-sided die, the variable will store a value ranging from 1 to 6.
Setting Up Initial
Values
The first task that the Die object must handle is to set up any variables
that are needed when the object is created. Insert a blank line after public
int value; and then enter the following:
public Die() {
value = 0;
}
This method is called a constructor because it is called automatically whenever
another program creates a Die object. The method does only one thing: It
sets the value variable equal to 0.
Rolling the Die
The next step is to write a method that handles the rolling of the die. Insert
a blank line at the bottom of your file and then enter the following:
public void rollValue(int maxValue) {
double tempValue = Math.random() * maxValue;
value = (int) Math.floor(tempValue) + 1;
}
This method takes one argument, an integer called maxValue. This value
will be used to indicate the number of sides on the die. The program you're writing,
a Craps applet, always uses six-sided dice. However, by using an argument
to enable other types of dice to be used, you make the Die class of objects
more useful with other projects you might undertake.
Two methods of the Math class are used in the rollValue() method:
Math.floor() and Math.random(). The Math class is one
of the standard class libraries that are part of the Java language, and it has several
functions to handle mathematic operations. Math.random() generates a random
number ranging from 0.0 to 1.0. These numbers are long floating-point numbers such
as the following:
When you multiply Math.random() by a value, you create a random number
ranging from 0 to within .001 of that value. For instance, multiplying Math.random()
by 6 generates a number ranging from 0.0 to almost 6.0. Adding 1 to this, as the
rollValue() method does, generates a random number from 1.0 to almost 7.0.
But just try rolling a six-sided die until you come up with 2.71570402264! To
create a dice-like effect, the number must be rounded down to an integer. The Math.floor()
method does exactly this. By using both floor() and random(), the
rollValue() method generates a random number from 1 to maxValue
and stores the number in the value variable.
Drawing the Die
The last thing the Die class of objects needs to do is draw the die.
Instead of displaying the value of the die as text, you can make your program more
appealing by showing the die on-screen. Java has several different polygon-drawing
methods that you can use to depict a die. The final look of a die depends on its
value. Figure 21.1 shows six dice with values that range from 1 to 6.
Figure
21.1.The possible values on a six-sided
die.
You can show dice in a computer program by drawing a rectangle with rounded corners
and circles for each number on a side. One way to handle this procedure in a Java
program would be to use a switch-case block with six different
sets of drawing statements. One dot could be drawn for a 1, two dots could depict
a 2, and so on. However, this solution involves a lot of redundant statements because
many of the faces on a six-sided die contain the same dots. As you can see in Figure
21.1, values 2 through 6 all have dots in the upper-left corner and lower-right corner.
Using switch and case would require the same statements to be repeated
five times for these dots.
Instead of repeating the same statements in several places, you can take a different
approach. Figure 21.2 shows each dot that might be seen on a die and the values that
are associated with the dot. You can use this information to draw a die more simply.
Listing 21.1 shows the full source code of the file Die.java. All of
the statements you have entered up to this point should look like Lines 1-13. Go
to the bottom of your file and insert Lines 14-37 of Listing 21.1. Save the file
when you're done.
Figure
21.2.Matching the dots to the values
associated with them.
Listing 21.1. The
source code of Die.java.
1: import java.awt.*;
2:
3: public class Die {
4: public int value;
5:
6: public Die() {
7: value = 0;
8: }
9:
10: public void rollValue(int maxValue) {
11: double tempValue = Math.random() * maxValue;
12: value = (int) Math.floor( tempValue ) + 1;
13: }
14:
15: public void drawDie(Graphics screen, int x, int y) {
16: screen.setColor(Color.red);
17: screen.fillRoundRect(x, y, 100, 100, 20, 20);
18: screen.setColor(Color.black);
19: screen.drawRoundRect(x, y, 100, 100, 20, 20);
20: screen.setColor(Color.white);
21: if (value > 1) {
22: screen.fillOval(x+5, y+5, 20, 20);
23: screen.fillOval(x+75, y+75, 20, 20);
24: }
25: if (value > 3) {
26: screen.fillOval(x+75, y+5, 20, 20);
27: screen.fillOval(x+5, y+75, 20, 20);
28: }
29: if (value == 6) {
30: screen.fillOval(x+5, y+40, 20, 20);
31: screen.fillOval(x+75, y+40, 20, 20);
32: }
33: if (value % 2 == 1) {
34: screen.fillOval(x+40, y+40, 20, 20);
35: }
36: }
37: } The drawDie() method takes three arguments:
A Graphics object indicates where all graphics operations should be
displayed. In the Craps program you'll be writing, all drawing will take
place on the applet's main window.
The two integers (x and y) determine the x and y coordinates
where the die should be drawn.
The following things are taking place in the drawDie() method:
Line 16 sets the current color to red using the red variable of the
Color class. All drawing methods that are used after this statement will
appear in red until the current color is changed again.
Line 17 draws a filled rectangle with rounded corners, so a red box appears on-screen
that looks like a die without any numbers on it. The first two arguments to fillRoundRect
are the x and y coordinates of the rectangle. These arguments use the same x and
y values that were sent to the drawDie() method in Line 14. The next two
arguments, 100, 100, designate the height and width of the rectangle in
pixels. The final two arguments, 20, 20, determine how rounded the rectangle's
corners should appear. The higher the number, the more rounded the corners appear
to be.
Line 18 sets the current color to black.
Line 19 draws an unfilled rectangle with rounded corners using the same arguments
as the red rectangle that already has been drawn. This line creates a black outline
around the red die.
Line 20 sets the current color to white.
Lines 21-35 draw white circles on the die using the fillOval() method.
Which circles are drawn depends on the value variable, which keeps track
of the die's value. The fillOval() method has four arguments. The first
two represent the x and y coordinates of the oval, and the last two represent the
height and width of the oval. Because the height and width are equal in these statements
(20, 20), the ovals are circles.
Lines 21-24 are handled only if the value variable is greater than one.
They draw circles in the upper-left and lower-right corners of the die. On a six-sided
die, all numbers from 2 upward have circles in these corners.
Lines 25-28 are handled only if the value variable is greater than 3.
They draw circles in the upper-right and lower-left corners of the die.
Lines 29-32 are handled only if value equals 6. They draw circles in
the middle of the left side and the middle of the right side of the die.
Lines 33-35 take care of the last circle that might be found on a die--the one
in the center. This circle is present in the numbers 1, 3, and 5. All of these are
odd numbers. Because the modulus operator % produces the remainder of a
division operation, you can take advantage of the fact that odd numbers divided by
2 have a remainder of 1, and even numbers have no remainder. The expression value
% 2 only equals 1 when value is an odd number. Lines 33-35 draw a circle
in the center of the die for odd-numbered die values.
Line 36 marks the end of the drawDie() method, and Line 37 marks the
end of the Die class.
Save the file, using the name Die.java, and compile it. Once it compiles
successfully, you will have a Die class of objects that can be used in any
program where you want to use six-sided dice.
Testing the Die
Class
The Die class of objects that you have created isn't intended to function
as a stand-alone program. If you tried to run it with the java tool, it
would result in an error because there is no main() statement in the Die
class. To try out your new class, you need to use it inside another Java program.
You can do this in the same way you used classes such as Math, Graphics,
and Color in your Die class. Create a new file with your word processor
and call it TestDie.java. Enter the text of Listing 21.2 and save the file.
Listing 21.2. The
full source code of TestDie.java.
1: class TestDie {
2: public static void main(String[] arguments) {
3: Die firstDie = new Die();
4: Die secondDie = new Die();
5: firstDie.rollValue(6);
6: secondDie.rollValue(6);
7: System.out.println("The first die rolled a " + firstDie.value);
8: System.out.println("The second die rolled a " + secondDie.value);
9: }
10: }
This program creates two dice called firstDie and secondDie, rolls
each of them using the rollValue() method, and displays the value stored
in the value variable of each Die object. The argument of 6
is used with the rollValue() method in Lines 5 and 6. This argument causes
a dice roll ranging from 1 to 6 to occur, and the result is stored in value.
Compile TestDie.java and run it from the command line with the java
tool. The output should resemble the following:
The first die rolled a 2
The second die rolled a 5
Run it several times to see that the rolls of the dice are random.
As with most programming languages, Java does not generate completely random numbers.
However, the results are random enough for most uses. One use that the Random
class would not be sufficient for is encryption. Java 1.1 introduces a new subclass
of Random called SecureRandom. This class can be used in Java programs
that encrypt information so that it cannot be viewed without being decrypted first.
Summary
This hour provided some practical experience with the object-oriented approach
of the Java language. The Die class of objects that you created simulates
the behavior of a type of real-world object: a six-sided die. Object-oriented programming
requires more initial effort than some other approaches, but it has several advantages:
The structure of the program is more familiar because objects share features
such as constructor methods and class variables.
The program is self-contained, so you can understand what it does without looking
at any other programs.
The program can be instantly reused with other programs.
You now have the Die class of objects to use whenever a die needs to
be used in a program. You'll be using it in a Craps applet in the coming
hour.
Q&A
Q Does the Craps applet require the use of a class of objects to represent
the dice?
A It's not a requirement--you could combine all the dice-related tasks and the
scorekeeping tasks into the same Java program. If you look at the source code of
applets that are available on the World Wide Web, you'll see many that handle all
of their functionality within a single program. However, this type of structure doesn't
take advantage of the benefits of object-oriented programming, and the program is
harder to understand, harder to reuse elsewhere, and more prone to bugs.
Q Does the public statement in front of a variable declaration mean that the variable
can be modified from other Java programs?
A Yes. As you'll see in the Craps applet in the next hour, you can change
the value of public variables in other objects. If you create a Die
object with the name firstDie, you can set its value variable with
a statement such as the following:
firstDie.value = 0;
Q Can you have more than one constructor method in a class of objects?
A You can have more than one constructor method if they have different argument
lists within their parentheses. One constructor could have no arguments, as in public
Die(), and another permitted constructor could be public Die(int maxValue).
One would be used when Die() is used in a program without any arguments,
and the other would be used when Die() is used with a single integer as
an argument.
Q Where can I find out the full list of classes that I can use in my Java programs
and the public methods that can be used with these classes?
A The Java Developer's Kit includes a large number of Web pages that document
all classes that are standard parts of the Java programming language. You also can
view these pages at the JavaSoft Web site with any Web browser. Visit the following
page:
Q What colors can be used in conjunction with the setColor() method?
A In addition to red, black, and white, you can use
the following variables as an argument to setColor(): blue, cyan,
darkGray, gray, green, lightGray, magenta,
orange, pink, and yellow. There also are methods of the
Color class that can be used to create a color based on RGB values, a popular
system for specifying a wide range of possible colors. RGB values are used on Web
pages with the BGCOLOR attribute of the <BODY> tag.
Quiz
Roll the dice and put your knowledge of object creation on the line by answering
the following questions.
Questions
1. What's the name for a method that is automatically called when an object
is created?
(a) an automat (b) a constructor (c) an init() method
2. In Java, which of the following isn't a synonym for program?
(a) a class (b) a method (c) an object
3. What's the name of the method in the Math class that rounds a number
down to the next lowest integer?
(a) floor() (b) round() (c) below()
Answers
1. b. An object's constructor method is called when it is created. The
init() method might sound familiar because it's handled automatically when
an applet is first loaded.
2. b. A program also can be considered as a class of objects or an object itself.
3. a. The round() method adds 0.5 to a number before finding the next
lowest integer, rounding it off to the closest integer.
Activities
Before you continue to the Craps applet, you can expand your knowledge
of this hour's topics with the following activities:
To see whether the random() method really generates random numbers,
create a short application that rolls 10,000 dice, using an array of integers to
keep track of how many times each value from 1 to 6 is rolled. When the dice have
finished rolling, display the contents of the array.
Add an argument to the drawDie() method that determines the color of
the die. Use a Color object for the argument so you can send values such
as Color.blue and Color.yellow to the method.