Java Free Tutorial

Web based School


Chapter 21

Playing Games with Java

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:

0.7359693177023363
0.5431408045289557
0.03239819056314541

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:
http://www.javasoft.com/products/JDK/1.1/docs/


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
an init() method

2.
In Java, which of the following isn't a synonym for program?

(a) a class
(b) a method
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()
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.