Hour 22

Writing a Game for the Web

With the Die class you created during the last hour, you can add dice to any of your Java programs. The Craps program that you will be writing during this hour uses two dice. Most of the tasks you have to handle in your game are taken care of by the Die class. What's left for your Craps applet is to display information to users, take input from users, and keep score.

The following topics will be covered during this hour:

Creating an Applet

All applets that you create will have some methods in common. The init() method is called when an applet loads on a page for the first time; you can use this method to set up variables and handle other startup tasks. The paint() method is called whenever something should be updated on the display. It also can be called within a program with the repaint(); statement. The init() and paint() methods will be used in your Craps applet. You also will use the actionPerformed() method, which is called whenever a user does something to a graphical item such as clicking on a button or hitting Enter in a text field.

Create a skeletal version of Craps that can be filled in during the hour as each section of the program is discussed. Create a new file in your word processor and enter Listing 22.1. Save it under the name Craps.java, making sure that it is saved in the same directory as Die.java and Die.class.

Listing 22.1. The starting source code of Craps.java.


 1: import java.awt.*;
 2: import java.awt.event.*;
 3:
 4: public class Craps extends java.applet.Applet implements ActionListener {
 5:     // create variables here
 6:
 7:     public void init() {
 8:         // initialize program
 9:     }
10:
11:     public void paint(Graphics screen) {
12:         // display stuff
13:     }
14:
15:     public void actionPerformed(ActionEvent event) {
16:         // receive user input
17:     }
18:
19:      public void checkResult(Die d1, Die d2) {
20:         // check roll and keep score
21:     }
22: } 


In addition to the init(), paint(), and actionPerformed() methods, this skeletal version of the Craps applet includes a checkResult() method with two Die objects as parameters. As you will see, this method is used to check the results of a dice roll and keep score.

Create Variables to Use

The first task in the Craps applet is to set up all variables that are going to be used in the program. In your word processor, delete the comment line // create variables here and enter Listing 22.2 in its place.

Listing 22.2. Setting up variables in Craps.java.


 1: Die die1 = new Die();
 2: Die die2 = new Die();
 3: int wins = 0;
 4: int losses = 0;
 5: int point = 0;
 6: final String WINNER = "WINNER";
 7: final String LOSER = "CRAPS!";
 8: String resultText = "";
9: Button rollButton = new Button("Roll Dice"); 


Lines 1 and 2 create new Die variables called die1 and die2. These variables are set up in the same way other variables such as strings are created by using the class name, variable name, and the new statement. When this statement is handled in your program, a constructor method of the Die class is called. Because there's nothing in between the parentheses in new Die(), the matching constructor with no arguments is called in the Die class.

In Lines 3 and 4, two integer variables are used to keep track of a user's win/loss record: wins and losses. The point integer variable in Line 5 stores the point, which is the dice total that must be rolled to win in a craps game after the first roll.

Lines 6 and 7 create strings named WINNER and LOSER. The final statement is used to declare that these variables are constants. A constant is a variable that will never change in value as a program runs. To provide another hint that the variables are constants, the names WINNER and LOSER are capitalized.

Because constants never change in value, you might wonder why one should ever be used. You could just use the value of the constant throughout the program. The advantage of using constants is that they can make a program easier to understand. For example, the variables Font.BOLD and Font.ITALIC are constants that hold integer values representing the style of the current font. The statement Font("Helvetica", Font.BOLD, 12) provides more information than Font("Helvetica", 1, 12) does, and both statements make 12-point Helvetica Bold the current font for text display.

Line 8 sets up a string called resultText and sets it up with an initial value of ""--an empty string. The last line, 9, creates a Button object called rollButton. As this object is created, the string "Roll Dice" is sent to the constructor method of the object. Button is a class of objects that handle the display and function of clickable user buttons. The rollButton object is given the label Roll Dice. This button is shown in the applet window, and it gives the user a chance to request a dice roll.

Set Up Variables and the Initial Display

A few things need to be done when the Craps applet first runs on a Web page. You need to choose a background color for the window and add the Button object rollButton to the window. To do these things, replace the comment line // initialize program with Listing 22.3.

Listing 22.3. The statements inside the init() method of Craps.java.


1: setBackground(Color.green);
2: rollButton.addActionListener(this);
3: add(rollButton); 


In Line 1 of Listing 22.3, the constant Color.green is used with the setBackground() method to choose green as the background color of the applet window. When the paint() method is called automatically to display the applet on-screen, it uses the color defined in setBackground(). If there is no setBackground() statement in a Java program, the default is gray.

Line 2 makes it possible for the rollButton object to generate action events when it is clicked. This is done by using the addActionListener() method, which is part of the ActionListener interface. Line 3 adds the rollButton object to the applet window.

Display Text and Graphics

The paint() method is called any time the text and graphics on-screen should be updated. This situation occurs when the program is run to draw something onto a blank window. The paint() method also can be called any time one of the following takes place:

In your growing Craps.java file, delete the comment line // display stuff inside the paint() method. Replace it with Listing 22.4.

Listing 22.4. The statements inside the paint() method of Craps.java.


 1: die1.drawDie(screen, 5, 50);
 2: die2.drawDie(screen, 175, 50);
 3: screen.setColor(Color.black);
 4: Font f = new Font("Helvetica", Font.BOLD, 15);
 5: screen.setFont(f);
 6: if (point != 0)
 7:     screen.drawString(point + " wins and 7 craps out.", 5, 200);
 8: else
 9:     screen.drawString("7 or 11 win; 2, 3, or 12 crap out.", 5, 200);
10: screen.drawString("Number of wins: " + wins, 5, 220);
11: screen.drawString("Number of losses: " + losses, 5, 240);
12: if (resultText != "") {
13:     f = new Font("Helvetica", Font.BOLD, 30);
14:     screen.setFont(f);
15:     screen.drawString(resultText, 85, 110);
16:     resultText = "";
17: } The following things are taking place in this method:

The text that is displayed in the paint() method depends on several things that are going on in other parts of the program. Because the rolls needed to win or lose change at different points in a game, paint() uses the value of point to determine what should be displayed. The variable point equals 0 at the beginning of a new game of craps because there is no point until the first roll is over. The resultText variable is displayed only when a game is over. It is set initially in another part of the program, the checkResult() method.

Handle User Input

Go to the spot in your Craps program with the comment line // receive user input and replace it with Listing 22.5.

Listing 22.5. The statements inside the actionPerformed() method of Craps.java.


1:     die1.rollValue(6);
2:     die2.rollValue(6);
3:     checkResult(die1, die2);
4: repaint(); 


As you learned during Hour 20, "Responding to User Events," the actionPerformed() method is called whenever an action event occurs on a component that can send out those events. The Craps applet has only one user interface component, a Button object called rollButton, which has been set up with an ActionListener object so it can generate action events.

The rollButton object in this program is labeled with the text Roll Dice. When the button is clicked, Lines 1 and 2 call the rollValue() method of each Die object. The argument, 6, indicates that a number from 1 to 6 should be rolled on each die. When a Die is rolled, the value variable is updated with the die's new value.

After the dice roll, you should see whether the new total of the dice is a winner or loser. You do this by calling the checkResult() method of the applet with two arguments: die1 and die2, the two Die objects. The checkResult() method is detailed in the next section.

Line 4 calls the repaint() method to force the screen to be updated. This method is needed because the dice and other information change with each roll, and those changes should be reflected on-screen.

Check Roll Results and Keep Score

The last thing to handle in the Craps applet is scorekeeping. The checkResult() method of your program takes two Die objects as arguments. Delete the comment line // check roll and keep score and replace it with Listing 22.6.

Listing 22.6. The statements inside the checkResult() method of Craps.java.


 1: if (point == 0) {
 2:     point = d1.value + d2.value;
 3:     if ( (point == 7) | (point == 11) )
 4:         resultText = WINNER;
 5:     if ( (point < 4) | (point == 12) )
 6:         resultText = LOSER;
 7: } else {
 8:     if (d1.value + d2.value == point)
 9:         resultText = WINNER;
10:     if (d1.value + d2.value == 7)
11:         resultText = LOSER;
12: }
13: if (resultText == WINNER) {
14:     wins++;
15:     point = 0;
16: }
17: if (resultText == LOSER) {
18:     losses++;
19:     point = 0;
20: } 


Lines 2 -6 of this method are handled only if the point variable is equal to 0. The point variable is used throughout this program as an indicator of the current stage of the craps game. When point equals 0, it shows that the current craps game has just finished its first roll, because the point has not been established yet. If point does not equal 0, the current game must be in its second or successive rolls. When point equals 0, Line 2 sets point to the sum of the value variables of both Die objects. The value variable keeps track of each die's current value in the game.

Lines 3-6 determine whether a winning roll or a losing roll has happened in the first roll of a craps game. The dice totals of 7 and 11 are winners, and the totals of 2, 3, or 12 are losers. The OR operator | is used in Lines 3 and 5, so if either one equality test or the other is true, the following statement is handled. If point is equal to 7 or point is equal to 11, the resultText variable is set to the value of the WINNER variable, which is the text WINNER. If point is less than 4 or point is equal to 12, resultText is set to the value of the LOSER variable, which is CRAPS!.

Lines 8-11 of this method are handled only if point did not equal 0 in Line 1. Line 8 tests whether the current total of the dice is equal to point. If it is, the resultText variable is set to the value of the WINNER variable, which is WINNER. Line 10 tests whether the current dice total equals 7. If it does, resultText is set to equal the LOSER variable, which is CRAPS!

Lines 13-16 are handled if resultText is equal to the WINNER variable, which indicates that the current dice roll was a winner. The wins variable is increased by 1 in Line 14 by the increment operator ++. Also, the point variable is set to 0 in Line 15 so that a new game can begin.

Lines 17-20 are handled if resultText is equal to the LOSER variable. These lines cause the losses variable to increase by 1 and point to be set to 0 in Line 19.

When you're done adding these statements inside the checkResult() method, your program should resemble Listing 22.7. The only differences should be if you indented the program differently, but all statements should be identical. Save your Craps.java file.

Listing 22.7. The complete source code of Craps.java.


 1: import java.awt.*;
 2: import java.awt.event.*;
 3:
 4: public class Craps extends java.applet.Applet implements ActionListener {
 5:     Die die1 = new Die();
 6:     Die die2 = new Die();
 7:     int wins = 0;
 8:     int losses = 0;
 9:     int point = 0;
10:     final String WINNER = "WINNER";
11:     final String LOSER = "CRAPS!";
12:     String resultText = "";
13:     Button rollButton = new Button("Roll Dice");
14:
15:     public void init() {
16:         setBackground(Color.green);
17:         rollButton.addActionListener(this);
18:         add(rollButton);
19:     }
20:
21:     public void paint(Graphics screen) {
22:         die1.drawDie(screen, 5, 50);
23:         die2.drawDie(screen, 175, 50);
24:         screen.setColor(Color.black);
25:         Font f = new Font("Helvetica", Font.BOLD, 15);
26:         screen.setFont(f);
27:         if (point != 0)
28:             screen.drawString(point + " wins and 7 craps out.", 5, 200);
29:         else
30:             screen.drawString("7 or 11 win; 2, 3, or 12 crap out.", 5, 200);
31:         screen.drawString("Number of wins: " + wins, 5, 220);
32:         screen.drawString("Number of losses: " + losses, 5, 240);
33:         if (resultText != "") {
34:             f = new Font("Helvetica", Font.BOLD, 30);
35:             screen.setFont(f);
36:             screen.drawString(resultText, 85, 110);
37:             resultText = "";
38:         }
39:     }
40:
41:     public void actionPerformed(ActionEvent event) {
42:         die1.rollValue(6);
43:         die2.rollValue(6);
44:         checkResult(die1, die2);
45:         repaint();
46:     }
47:
48:     public void checkResult(Die d1, Die d2) {
49:         if (point == 0) {
50:             point = d1.value + d2.value;
51:             if ( (point == 7) | (point == 11) )
52:                 resultText = WINNER;
53:             if ( (point < 4) | (point == 12) )
54:                 resultText = LOSER;
55:         } else {
56:             if (d1.value + d2.value == point)
57:                 resultText = WINNER;
58:             if (d1.value + d2.value == 7)
59:                 resultText = LOSER;
60:         }
61:         if (resultText == WINNER) {
62:             wins++;
63:             point = 0;
64:         }
65:         if (resultText == LOSER) {
66:             losses++;
67:             point = 0;
68:         }
69:     }
70: } Compile the Craps.java file using the following command:
javac Craps.java

After fixing any errors that are caused by typos, you're almost ready to test the program.

Putting the Program on a Page

Because the Craps program is an applet, it was designed to run only as part of a World Wide Web page. To place the applet on a Web page, create a new file called Craps.html. Enter Listing 22.8 and save the file in the same directory as Craps.java and Craps.class.

Listing 22.8. The source code of Craps.html.


 1: <html>
 2: <head>
 3: <title>Craps applet</title>
 4: </head>
 5: <body>
 6: <applet code="Craps.class" width=285 height=250>
 7: </applet>
 8: </body>
9: </html> 


Most of the HTML tags on the page are just standard tags that are included on any Web page. The width and height attributes of the <applet> tag determine how big the applet will appear on a page. You can use any dimensions and the applet will still run because Java creates programs that are flexible when it comes to how they are displayed. For optimal appearance, however, use a width of 285 and a height of 250.

In order to see the applet, you need to use a Web browser that can handle Java programs. At the time of this writing, the current versions of Netscape Navigator and Microsoft Internet Explorer cannot handle new features introduced in version 1.1 of the Java language. You have to use the appletviewer tool that comes with the Java Developer's Kit to test the Craps applet. If you're in the same directory as the Craps.html file, the following command will cause appletviewer to load the applet:

appletviewer Craps.html

Figure 22.1 shows the output of the Craps applet using appletviewer. Run the program several times to see the different ways that text and each of the dice can be displayed. Because the dice are drawn with polygons instead of by loading a picture of a die, the applet updates the graphics quickly as you play.

Figure 22.1. The Craps applet on a Web page viewed with the appletviewer tool.

Summary

The Craps applet that you have written shows how you can use Java to offer games on a Web site. The step-by-step process of creating a program was detailed, including some of the planning that occurs before you sit down at the computer. Because many of the program's tasks involved rolling or displaying dice, you created a special Die object to handle all of this functionality. Creating this object enables you to use some of the work you did for the Craps applet in other programs later on.

You can use this applet on a Web page in its completed form, and all that is required are the files Die.class and Craps.class and a Web page with HTML tags to load the applet. Thanks to the global reach of the World Wide Web and Java, you can bring the seedy charm of craps games to everyone from Afghanistan to Zambia, including Pia Zadora.

Q&A

Q Do I need to use an import statement to use the Die class or another class of objects that I create in a program?

A
If the class you want to use is in the same directory as your program, an import statement is not required. The import statement makes Java's standard classes available in a program. Place special classes that you create and other classes that you find on the Web or in books in the same directory as the programs that use them.

Q Isn't constant variable an oxymoron?

A
Constants never change and variables can change at any time, but it's convenient to call both variables because they serve the same function. Each stores a value for use as a program runs. The final statement is not needed to make a variable a constant in a program--WINNER and LOSER would work the same in the Craps applet without final. However, it's much safer in your programs to ensure that a constant remains constant.

Q When x and y coordinates are specified in a drawString() statement, where are the x and y coordinates in relation to the text that is displayed?

A
Imagine that there is an invisible box around the text that is exactly big enough to hold all of the characters. The upper-left corner of this box is the intersection of the x and y coordinates specified as arguments to drawString().

Quiz

If you've become a gambler thanks to this hour's lesson, feel free to make wagers on your knowledge of programming before you answer the following questions.

Questions

1. What can you do to make the name of a constant stand out in a program?

(a) Use a foreign language.
(b) Capitalize the first letter.
(c) Capitalize the whole name.

2.
What method sets the color of the window in an applet?

(a) setBackground()
(b) setColor()
(c) setWindow()

3.
If the first dice roll in a craps game isn't a winner or a loser, what do you call the total of the roll?

(a) the punt
(b) the point
(c) the pint

Answers

1. c. If you only capitalize the first letter, the constant name will look just like the names of classes in your programs.

2.
a. setColor() sets the current color for all successive graphical methods.

3.
b.

Activities

Now that you have completed your most sophisticated Java project thus far, you can build your skills with the following activities: