Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Intro_Java_brief_Liang2011.pdf
Скачиваний:
194
Добавлен:
26.03.2016
Размер:
10.44 Mб
Скачать

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

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]