- •CONTENTS
- •1.1 Introduction
- •1.2 What Is a Computer?
- •1.3 Programs
- •1.4 Operating Systems
- •1.5 Java, World Wide Web, and Beyond
- •1.6 The Java Language Specification, API, JDK, and IDE
- •1.7 A Simple Java Program
- •1.8 Creating, Compiling, and Executing a Java Program
- •1.9 (GUI) Displaying Text in a Message Dialog Box
- •2.1 Introduction
- •2.2 Writing Simple Programs
- •2.3 Reading Input from the Console
- •2.4 Identifiers
- •2.5 Variables
- •2.7 Named Constants
- •2.8 Numeric Data Types and Operations
- •2.9 Problem: Displaying the Current Time
- •2.10 Shorthand Operators
- •2.11 Numeric Type Conversions
- •2.12 Problem: Computing Loan Payments
- •2.13 Character Data Type and Operations
- •2.14 Problem: Counting Monetary Units
- •2.15 The String Type
- •2.16 Programming Style and Documentation
- •2.17 Programming Errors
- •2.18 (GUI) Getting Input from Input Dialogs
- •3.1 Introduction
- •3.2 boolean Data Type
- •3.3 Problem: A Simple Math Learning Tool
- •3.4 if Statements
- •3.5 Problem: Guessing Birthdays
- •3.6 Two-Way if Statements
- •3.7 Nested if Statements
- •3.8 Common Errors in Selection Statements
- •3.9 Problem: An Improved Math Learning Tool
- •3.10 Problem: Computing Body Mass Index
- •3.11 Problem: Computing Taxes
- •3.12 Logical Operators
- •3.13 Problem: Determining Leap Year
- •3.14 Problem: Lottery
- •3.15 switch Statements
- •3.16 Conditional Expressions
- •3.17 Formatting Console Output
- •3.18 Operator Precedence and Associativity
- •3.19 (GUI) Confirmation Dialogs
- •4.1 Introduction
- •4.2 The while Loop
- •4.3 The do-while Loop
- •4.4 The for Loop
- •4.5 Which Loop to Use?
- •4.6 Nested Loops
- •4.7 Minimizing Numeric Errors
- •4.8 Case Studies
- •4.9 Keywords break and continue
- •4.10 (GUI) Controlling a Loop with a Confirmation Dialog
- •5.1 Introduction
- •5.2 Defining a Method
- •5.3 Calling a Method
- •5.4 void Method Example
- •5.5 Passing Parameters by Values
- •5.6 Modularizing Code
- •5.7 Problem: Converting Decimals to Hexadecimals
- •5.8 Overloading Methods
- •5.9 The Scope of Variables
- •5.10 The Math Class
- •5.11 Case Study: Generating Random Characters
- •5.12 Method Abstraction and Stepwise Refinement
- •6.1 Introduction
- •6.2 Array Basics
- •6.3 Problem: Lotto Numbers
- •6.4 Problem: Deck of Cards
- •6.5 Copying Arrays
- •6.6 Passing Arrays to Methods
- •6.7 Returning an Array from a Method
- •6.8 Variable-Length Argument Lists
- •6.9 Searching Arrays
- •6.10 Sorting Arrays
- •6.11 The Arrays Class
- •7.1 Introduction
- •7.2 Two-Dimensional Array Basics
- •7.3 Processing Two-Dimensional Arrays
- •7.4 Passing Two-Dimensional Arrays to Methods
- •7.5 Problem: Grading a Multiple-Choice Test
- •7.6 Problem: Finding a Closest Pair
- •7.7 Problem: Sudoku
- •7.8 Multidimensional Arrays
- •8.1 Introduction
- •8.2 Defining Classes for Objects
- •8.3 Example: Defining Classes and Creating Objects
- •8.4 Constructing Objects Using Constructors
- •8.5 Accessing Objects via Reference Variables
- •8.6 Using Classes from the Java Library
- •8.7 Static Variables, Constants, and Methods
- •8.8 Visibility Modifiers
- •8.9 Data Field Encapsulation
- •8.10 Passing Objects to Methods
- •8.11 Array of Objects
- •9.1 Introduction
- •9.2 The String Class
- •9.3 The Character Class
- •9.4 The StringBuilder/StringBuffer Class
- •9.5 Command-Line Arguments
- •9.6 The File Class
- •9.7 File Input and Output
- •9.8 (GUI) File Dialogs
- •10.1 Introduction
- •10.2 Immutable Objects and Classes
- •10.3 The Scope of Variables
- •10.4 The this Reference
- •10.5 Class Abstraction and Encapsulation
- •10.6 Object-Oriented Thinking
- •10.7 Object Composition
- •10.8 Designing the Course Class
- •10.9 Designing a Class for Stacks
- •10.10 Designing the GuessDate Class
- •10.11 Class Design Guidelines
- •11.1 Introduction
- •11.2 Superclasses and Subclasses
- •11.3 Using the super Keyword
- •11.4 Overriding Methods
- •11.5 Overriding vs. Overloading
- •11.6 The Object Class and Its toString() Method
- •11.7 Polymorphism
- •11.8 Dynamic Binding
- •11.9 Casting Objects and the instanceof Operator
- •11.11 The ArrayList Class
- •11.12 A Custom Stack Class
- •11.13 The protected Data and Methods
- •11.14 Preventing Extending and Overriding
- •12.1 Introduction
- •12.2 Swing vs. AWT
- •12.3 The Java GUI API
- •12.4 Frames
- •12.5 Layout Managers
- •12.6 Using Panels as Subcontainers
- •12.7 The Color Class
- •12.8 The Font Class
- •12.9 Common Features of Swing GUI Components
- •12.10 Image Icons
- •13.1 Introduction
- •13.2 Exception-Handling Overview
- •13.3 Exception-Handling Advantages
- •13.4 Exception Types
- •13.5 More on Exception Handling
- •13.6 The finally Clause
- •13.7 When to Use Exceptions
- •13.8 Rethrowing Exceptions
- •13.9 Chained Exceptions
- •13.10 Creating Custom Exception Classes
- •14.1 Introduction
- •14.2 Abstract Classes
- •14.3 Example: Calendar and GregorianCalendar
- •14.4 Interfaces
- •14.5 Example: The Comparable Interface
- •14.6 Example: The ActionListener Interface
- •14.7 Example: The Cloneable Interface
- •14.8 Interfaces vs. Abstract Classes
- •14.9 Processing Primitive Data Type Values as Objects
- •14.10 Sorting an Array of Objects
- •14.11 Automatic Conversion between Primitive Types and Wrapper Class Types
- •14.12 The BigInteger and BigDecimal Classes
- •14.13 Case Study: The Rational Class
- •15.1 Introduction
- •15.2 Graphical Coordinate Systems
- •15.3 The Graphics Class
- •15.4 Drawing Strings, Lines, Rectangles, and Ovals
- •15.5 Case Study: The FigurePanel Class
- •15.6 Drawing Arcs
- •15.7 Drawing Polygons and Polylines
- •15.8 Centering a String Using the FontMetrics Class
- •15.9 Case Study: The MessagePanel Class
- •15.10 Case Study: The StillClock Class
- •15.11 Displaying Images
- •15.12 Case Study: The ImageViewer Class
- •16.1 Introduction
- •16.2 Event and Event Source
- •16.3 Listeners, Registrations, and Handling Events
- •16.4 Inner Classes
- •16.5 Anonymous Class Listeners
- •16.6 Alternative Ways of Defining Listener Classes
- •16.7 Problem: Loan Calculator
- •16.8 Window Events
- •16.9 Listener Interface Adapters
- •16.10 Mouse Events
- •16.11 Key Events
- •16.12 Animation Using the Timer Class
- •17.1 Introduction
- •17.2 Buttons
- •17.3 Check Boxes
- •17.4 Radio Buttons
- •17.5 Labels
- •17.6 Text Fields
- •17.7 Text Areas
- •17.8 Combo Boxes
- •17.9 Lists
- •17.10 Scroll Bars
- •17.11 Sliders
- •17.12 Creating Multiple Windows
- •18.1 Introduction
- •18.2 Developing Applets
- •18.3 The HTML File and the <applet> Tag
- •18.4 Applet Security Restrictions
- •18.5 Enabling Applets to Run as Applications
- •18.6 Applet Life-Cycle Methods
- •18.7 Passing Strings to Applets
- •18.8 Case Study: Bouncing Ball
- •18.9 Case Study: TicTacToe
- •18.10 Locating Resources Using the URL Class
- •18.11 Playing Audio in Any Java Program
- •18.12 Case Study: Multimedia Animations
- •19.1 Introduction
- •19.2 How is I/O Handled in Java?
- •19.3 Text I/O vs. Binary I/O
- •19.4 Binary I/O Classes
- •19.5 Problem: Copying Files
- •19.6 Object I/O
- •19.7 Random-Access Files
- •20.1 Introduction
- •20.2 Problem: Computing Factorials
- •20.3 Problem: Computing Fibonacci Numbers
- •20.4 Problem Solving Using Recursion
- •20.5 Recursive Helper Methods
- •20.6 Problem: Finding the Directory Size
- •20.7 Problem: Towers of Hanoi
- •20.8 Problem: Fractals
- •20.9 Problem: Eight Queens
- •20.10 Recursion vs. Iteration
- •20.11 Tail Recursion
- •APPENDIXES
- •INDEX
628 Chapter 18 Applets and Multimedia
Video Note
TicTacToe
18.9 Case Study: TicTacToe
From the many examples in this and earlier chapters you have learned about objects, classes, arrays, class inheritance, GUI, event-driven programming, and applets. Now it is time to put what you have learned to work in developing comprehensive projects. In this section, you will develop a Java applet with which to play the popular game of TicTacToe.
Two players take turns marking an available cell in a 3 * 3 grid with their respective tokens (either X or O). When one player has placed three tokens in a horizontal, vertical, or diagonal row on the grid, the game is over and that player has won. A draw (no winner) occurs when all the cells on the grid have been filled with tokens and neither player has achieved a win. Figure 18.11 shows the representative sample runs of the example.
(a) The X player won the game |
(b) Draw-no winners |
(c) The O player won the game |
FIGURE 18.11 Two players play a TicTacToe game.
All the examples you have seen so far show simple behaviors that are easy to model with classes. The behavior of the TicTacToe game is somewhat more complex. To create classes that model the behavior, you need to study and understand the game.
Assume that all the cells are initially empty, and that the first player takes the X token, the second player the O token. To mark a cell, the player points the mouse to the cell and clicks it. If the cell is empty, the token (X or O) is displayed. If the cell is already filled, the player’s action is ignored.
From the preceding description, it is obvious that a cell is a GUI object that handles the mouse-click event and displays tokens. Such an object could be either a button or a panel. Drawing on panels is more flexible than drawing on buttons, because on a panel the token (X or O) can be drawn in any size, but on a button it can be displayed only as a text label. Therefore, a panel should be used to model a cell. How do you know the state of the cell (empty, X, or O)? You use a property named token of char type in the Cell class. The Cell class is responsible for drawing the token when an empty cell is clicked. So you need to write the code for listening to the MouseEvent and for painting the shapes for tokens X and O. The Cell class can be defined as shown in Figure 18.12.
javax.swing.JPanel
Cell |
|
|
|
|
|
-token: char |
|
Token used in the cell (default: ''). |
|
|
|
+getToken(): char |
|
Returns the token in the cell. |
+setToken(token: char): void |
|
Sets a new token in the cell. |
#paintComponent(g: Graphics): void |
|
Paints the token in the cell. |
+mouseClicked(e: MouseEvent): void |
|
Handles a mouse click on the cell. |
|
|
|
FIGURE 18.12 The Cell class paints the token on a cell.
18.9 Case Study: TicTacToe 629
The TicTacToe board consists of nine cells, created using new Cell[3][3]. To determine which player’s turn it is, you can introduce a variable named whoseTurn of char type. whoseTurn is initially X, then changes to O, and subsequently changes between X and O whenever a new cell is occupied. When the game is over, set whoseTurn to ' '.
How do you know whether the game is over, whether there is a winner, and who the winner, if any, is? You can create a method named isWon(char token) to check whether a specified token has won and a method named isFull() to check whether all the cells are occupied.
Clearly, two classes emerge from the foregoing analysis. One is the Cell class, which handles operations for a single cell; the other is the TicTacToe class, which plays the whole game and deals with all the cells. The relationship between these two classes is shown in Figure 18.13.
Cell javax.swing.JApplet
9
1
TicTacToe
-whoseTurn: char
-cell: Cell[][]
-jlblStatus: JLabel
+TicTacToe()
+isFull(): boolean
+isWon(token: char): boolean
FIGURE 18.13 The TicTacToe class contains nine cells.
Since the Cell class is only to support the TicTacToe class, it can be defined as an inner class in TicTacToe. The complete program is given in Listing 18.10:
LISTING 18.10 TicTacToe.java
1 |
import java.awt.*; |
|
||
2 |
import java.awt.event.*; |
|
||
3 |
import javax.swing.*; |
|
||
4 |
import javax.swing.border.LineBorder; |
|
||
5 |
|
|
|
|
6 |
public class |
TicTacToe extends JApplet |
{ |
main class TicTacToe |
7 |
// Indicate which player has a turn; initially it is the X player |
|
||
8 |
private char whoseTurn = 'X'; |
|
||
9 |
|
|
|
|
10// Create and initialize cells
11private Cell[][] cells = new Cell[3][3];
13// Create and initialize a status label
14private JLabel jlblStatus = new JLabel("X's turn to play");
16/** Initialize UI */
17public TicTacToe() {
18// Panel p to hold cells
19JPanel p = new JPanel(new GridLayout(3, 3, 0, 0));
20for (int i = 0; i < 3; i++)
21for (int j = 0; j < 3; j++)
22p.add(cells[i][j] = new Cell());
630 Chapter 18 |
Applets and Multimedia |
|||||||
|
23 |
|
|
|
|
|
|
|
|
24 |
// Set line borders on the cells panel and the status label |
||||||
|
25 |
p.setBorder(new LineBorder(Color.red, 1)); |
||||||
|
26 |
jlblStatus.setBorder(new LineBorder(Color.yellow, 1)); |
||||||
|
27 |
|
|
|
|
|
|
|
|
28 |
// Place the panel and the label to the applet |
||||||
|
29 |
add(p, BorderLayout.CENTER); |
||||||
|
30 |
add(jlblStatus, BorderLayout.SOUTH); |
||||||
|
31 |
} |
|
|
|
|
|
|
|
32 |
|
|
|
|
|
|
|
|
33 |
/** Determine whether the cells are all occupied */ |
||||||
check isFull |
34 |
public boolean isFull() |
{ |
|||||
|
35 |
for (int i = 0; i < 3; i++) |
||||||
|
36 |
for (int j = 0; j < 3; j++) |
||||||
|
37 |
|
if (cells[i][j].getToken() == ' ') |
|||||
|
38 |
|
return false; |
|||||
|
39 |
|
|
|
|
|
|
|
|
40 |
return true; |
||||||
|
41 |
} |
|
|
|
|
|
|
|
42 |
|
|
|
|
|
|
|
|
43 |
/** Determine whether the player with the specified token wins */ |
||||||
|
44 |
public boolean isWon(char token) |
{ |
|||||
check rows |
45 |
for (int i = 0; i < 3; i++) |
||||||
|
46 |
|
if ((cells[i][0].getToken() == token) |
|||||
|
47 |
|
&& (cells[i][1].getToken() == token) |
|||||
|
48 |
|
&& (cells[i][2].getToken() == token)) { |
|||||
|
49 |
|
return true; |
|||||
|
50 |
} |
|
|
|
|
|
|
|
51 |
|
|
|
|
|
|
|
check columns |
52 |
for (int j = 0; j < 3; j++) |
||||||
|
53 |
if ((cells[0][j].getToken() == token) |
||||||
|
54 |
|
&& (cells[1][j].getToken() == token) |
|||||
|
55 |
|
&& (cells[2][j].getToken() == token)) { |
|||||
|
56 |
|
return true; |
|||||
|
57 |
} |
|
|
|
|
|
|
|
58 |
|
|
|
|
|
|
|
check major diagonal |
59 |
if ((cells[0][0].getToken() == token) |
||||||
|
60 |
|
&& (cells[1][1].getToken() == token) |
|||||
|
61 |
|
&& (cells[2][2].getToken() == token)) { |
|||||
|
62 |
|
return true; |
|||||
|
63 |
} |
|
|
|
|
|
|
|
64 |
|
|
|
|
|
|
|
check subdiagonal |
65 |
if ((cells[0][2].getToken() == token) |
||||||
|
66 |
|
&& (cells[1][1].getToken() == token) |
|||||
|
67 |
|
&& (cells[2][0].getToken() == token)) { |
|||||
|
68 |
|
return true; |
|||||
|
69 |
} |
|
|
|
|
|
|
|
70 |
|
|
|
|
|
|
|
|
71 |
return false; |
||||||
|
72 |
} |
|
|
|
|
|
|
|
73 |
|
|
|
|
|
|
|
|
74 |
// An inner class for a cell |
||||||
inner class Cell |
75 |
public class |
Cell extends JPanel |
{ |
||||
|
76 |
// Token used for this cell |
||||||
|
77 |
private char token = ' '; |
||||||
|
78 |
|
|
|
|
|
|
|
|
79 |
public Cell() { |
||||||
|
80 |
setBorder(new LineBorder(Color.black, 1)); // Set cell's border |
||||||
register listener |
81 |
|
addMouseListener(new MyMouseListener()); |
// Register listener |
||||
|
82 |
} |
|
|
|
|
|
|
18.9 Case Study: TicTacToe 631
83
84/** Return token */
85public char getToken() {
86return token;
87}
88
89/** Set a new token */
90public void setToken(char c) {
91token = c;
92repaint();
93}
94 |
|
|
|
95 |
/** Paint the cell */ |
|
|
96 |
protected void paintComponent(Graphics g) |
{ |
paint cell |
97 |
super.paintComponent(g); |
|
|
98 |
|
|
|
99if (token == 'X') {
100g.drawLine(10, 10, getWidth() - 10, getHeight() - 10);
101g.drawLine(getWidth() - 10, 10, 10, getHeight() - 10);
102}
103else if (token == 'O') {
104g.drawOval(10, 10, getWidth() - 20, getHeight() - 20);
105}
106}
107 |
|
|
108 |
private class MyMouseListener extends MouseAdapter { |
listener class |
109/** Handle mouse click on a cell */
110public void mouseClicked(MouseEvent e) {
111// If cell is empty and game is not over
112if (token == ' ' && whoseTurn != ' ') {
113setToken(whoseTurn); // Set token in the cell
115// Check game status
116if (isWon(whoseTurn)) {
117jlblStatus.setText(whoseTurn + " won! The game is over");
118whoseTurn = ' '; // Game is over
119}
120else if (isFull()) {
121jlblStatus.setText("Draw! The game is over");
122whoseTurn = ' '; // Game is over
123}
124else {
125// Change the turn
126whoseTurn = (whoseTurn == 'X') ? 'O': 'X';
127// Display whose turn
128jlblStatus.setText(whoseTurn + "'s turn");
129}
130}
131}
132}
133}
134 } |
main method omitted |
The TicTacToe class initializes the user interface with nine cells placed in a panel of GridLayout (lines 19–22). A label named jlblStatus is used to show the status of the game (line 14). The variable whoseTurn (line 8) is used to track the next type of token to be placed in a cell. The methods isFull (lines 34-41) and isWon (lines 44–72) are for checking the status of the game.
Since Cell is an inner class in TicTacToe, the variable (whoseTurn) and methods (isFull and isWon) defined in TicTacToe can be referenced from the Cell class. The inner class makes