COMP2396
Loading...
Searching...
No Matches
game Class Reference

A simple Tic Tac Toe game with GUI. More...

Collaboration diagram for game:

Classes

enum  END_GAME_STATUS
 
enum  State
 

Public Member Functions

void go ()
 Initialize the GUI.
 
void go ()
 Initialize the GUI and establish connection to server.
 

Static Public Member Functions

static void main (String[] args)
 Main method to start the game.
 
static void main (String[] args)
 Main method to start the game.
 

Private Member Functions

END_GAME_STATUS checkWin ()
 Check if the game is over by looking at the board[][] array.
 
void closeConnection ()
 Close the connection to the server.
 
void enableGameBoard (boolean enable)
 Enable or disable the game board buttons based on the player's turn.
 
END_GAME_STATUS endGameCheck ()
 Responsible for popping a dialog box when the game ends.
 
String getLocalTime ()
 Get the current system time in 24 hour format.
 
String getLocalTime ()
 Get the current system time in 24-hour format without milliseconds.
 
void initializeConnection ()
 Establish connection to the server.
 
void resetBoard ()
 Reset the board to start a new game or due to opponent leaving.
 
void submitName ()
 Submit the player's name to the server.
 
void updateBoard (char symbol, int row, int col)
 Update the board with the move.
 

Detailed Description

A simple Tic Tac Toe game with GUI.

A two-player Tic Tac Toe game with GUI over the network.

COMP2396 Assignment 4

Author
@eric15342335 Cheng Ho Ming, Eric (3036216734)

COMP2396 Assignment 5

Author
Cheng Ho Ming, Eric (3036216734)

Definition at line 11 of file game.java.

Member Function Documentation

◆ checkWin()

END_GAME_STATUS game.checkWin ( )
inlineprivate

Check if the game is over by looking at the board[][] array.

Returns
END_GAME_STATUS.PLAYER_WIN if player wins, END_GAME_STATUS.COMPUTER_WIN if computer wins, END_GAME_STATUS.DRAW if draw, END_GAME_STATUS.CONTINUE if game continues

Definition at line 298 of file game.java.

298 {
299 // check rows
300 for (int i = 0; i < 3; i++) {
301 if (board[i][0] == State.PLAYER && board[i][1] == State.PLAYER && board[i][2] == State.PLAYER) {
302 return END_GAME_STATUS.PLAYER_WIN;
303 }
304 if (board[i][0] == State.COMPUTER && board[i][1] == State.COMPUTER && board[i][2] == State.COMPUTER) {
305 return END_GAME_STATUS.COMPUTER_WIN;
306 }
307 }
308 // check columns
309 for (int i = 0; i < 3; i++) {
310 if (board[0][i] == State.PLAYER && board[1][i] == State.PLAYER && board[2][i] == State.PLAYER) {
311 return END_GAME_STATUS.PLAYER_WIN;
312 }
313 if (board[0][i] == State.COMPUTER && board[1][i] == State.COMPUTER && board[2][i] == State.COMPUTER) {
314 return END_GAME_STATUS.COMPUTER_WIN;
315 }
316 }
317 // check diagonals
318 if (board[0][0] == State.PLAYER && board[1][1] == State.PLAYER && board[2][2] == State.PLAYER) {
319 return END_GAME_STATUS.PLAYER_WIN;
320 }
321 if (board[0][0] == State.COMPUTER && board[1][1] == State.COMPUTER && board[2][2] == State.COMPUTER) {
322 return END_GAME_STATUS.COMPUTER_WIN;
323 }
324 if (board[0][2] == State.PLAYER && board[1][1] == State.PLAYER && board[2][0] == State.PLAYER) {
325 return END_GAME_STATUS.PLAYER_WIN;
326 }
327 if (board[0][2] == State.COMPUTER && board[1][1] == State.COMPUTER && board[2][0] == State.COMPUTER) {
328 return END_GAME_STATUS.COMPUTER_WIN;
329 }
330 // check draw
331 if (board_filled == 9) {
332 return END_GAME_STATUS.DRAW;
333 }
334 return END_GAME_STATUS.CONTINUE;
335 }

References game.State.COMPUTER, game.END_GAME_STATUS.COMPUTER_WIN, game.END_GAME_STATUS.CONTINUE, game.END_GAME_STATUS.DRAW, game.State.PLAYER, and game.END_GAME_STATUS.PLAYER_WIN.

Referenced by endGameCheck().

Here is the caller graph for this function:

◆ closeConnection()

void game.closeConnection ( )
inlineprivate

Close the connection to the server.

Definition at line 529 of file game.java.

529 {
530 try {
531 if (out != null) out.close();
532 if (in != null) in.close();
533 if (socket != null) socket.close();
534 } catch (IOException e) {
535 // Ignore exceptions
536 }
537 }

Referenced by go(), and initializeConnection().

Here is the caller graph for this function:

◆ enableGameBoard()

void game.enableGameBoard ( boolean enable)
inlineprivate

Enable or disable the game board buttons based on the player's turn.

Parameters
enableTrue to enable, false to disable

Definition at line 501 of file game.java.

501 {
502 Component[] components = gameBoard.getComponents();
503 for (Component component : components) {
504 JButton button = (JButton)component;
505 button.setEnabled(false);
506 if (button.getText().equals(" ")) {
507 button.setEnabled(enable);
508 }
509 button.setUI(new MetalButtonUI() {
510 protected Color getDisabledTextColor() {
511 return button.getForeground();
512 }
513 });
514 button.setFocusPainted(false);
515 }
516 }

Referenced by initializeConnection().

Here is the caller graph for this function:

◆ endGameCheck()

END_GAME_STATUS game.endGameCheck ( )
inlineprivate

Responsible for popping a dialog box when the game ends.

Also updates the score display. Otherwise, return END_GAME_STATUS.CONTINUE.

Returns
END_GAME_STATUS.PLAYER_WIN if player wins, END_GAME_STATUS.COMPUTER_WIN if computer wins, END_GAME_STATUS.DRAW if draw, END_GAME_STATUS.CONTINUE if game continues

Definition at line 263 of file game.java.

263 {
264 END_GAME_STATUS status = checkWin();
265 String message_delivered = "";
266 if (status == END_GAME_STATUS.PLAYER_WIN) {
267 message_delivered = "Player wins!";
268 playerScore.setText(Integer.parseInt(playerScore.getText()) + 1 + "");
269 } else if (status == END_GAME_STATUS.COMPUTER_WIN) {
270 message_delivered = "Computer wins!";
271 computerScore.setText(Integer.parseInt(computerScore.getText()) + 1 + "");
272 } else if (status == END_GAME_STATUS.DRAW) {
273 message_delivered = "It's a draw!";
274 drawScore.setText(Integer.parseInt(drawScore.getText()) + 1 + "");
275 } else {
276 return END_GAME_STATUS.CONTINUE;
277 }
278 Object[] options = {"Yes"};
279 JOptionPane.showOptionDialog(frame, message_delivered, "Game Over", JOptionPane.DEFAULT_OPTION, JOptionPane.INFORMATION_MESSAGE, null, options, options[0]);
280 // reset the game
281 for (int i = 0; i < 3; i++) {
282 for (int j = 0; j < 3; j++) {
283 board[i][j] = State.EMPTY;
284 }
285 }
286 board_filled = 0;
287 Component[] components = gameBoard.getComponents();
288 for (Component component : components) {
289 JButton button = (JButton)component;
290 button.setText(" ");
291 }
292 return status;
293 }
END_GAME_STATUS checkWin()
Check if the game is over by looking at the board[][] array.
Definition game.java:298

References checkWin(), game.END_GAME_STATUS.COMPUTER_WIN, game.END_GAME_STATUS.CONTINUE, game.END_GAME_STATUS.DRAW, game.State.EMPTY, and game.END_GAME_STATUS.PLAYER_WIN.

Referenced by go().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ getLocalTime() [1/2]

String game.getLocalTime ( )
inlineprivate

Get the current system time in 24 hour format.

Truncate the miliseconds precision.

Returns
String of the current time in HH:mm:ss format, e.g. "Current Time: 12:34:56"

Definition at line 251 of file game.java.

251 {
252 return "Current Time: " + java.time.LocalTime.now().format(java.time.format.DateTimeFormatter.ofPattern("HH:mm:ss"));
253 }

Referenced by go().

Here is the caller graph for this function:

◆ getLocalTime() [2/2]

String game.getLocalTime ( )
inlineprivate

Get the current system time in 24-hour format without milliseconds.

Returns
String representation of current time, e.g., "Current Time: 12:34:56"

Definition at line 522 of file game.java.

522 {
523 return "Current Time: " + java.time.LocalTime.now().format(java.time.format.DateTimeFormatter.ofPattern("HH:mm:ss"));
524 }

◆ go() [1/2]

void game.go ( )
inline

Initialize the GUI.

Set up the game board, player name input, and score display.

Parameters
void

Definition at line 43 of file game.java.

43 {
44 frame = new JFrame("Tic Tac Toe");
45 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
46 // top display
47 // "Enter your player name..." and "WELCOME {NAME}"
48 JPanel topPanel = new JPanel();
49 frame.add(topPanel, BorderLayout.NORTH);
50 welcomeLabel = new JLabel("Enter your player name...");
51 topPanel.add(welcomeLabel);
52 // bottom display with name input and time
53 JPanel bottomPanel = new JPanel();
54 bottomPanel.setLayout(new GridBagLayout());
55 frame.add(bottomPanel, BorderLayout.SOUTH);
56 // player name input: holds text, textfield, and submit button
57 JPanel playerNameInputElements = new JPanel();
58 bottomPanel.add(playerNameInputElements);
59 playerNameInputElements.setLayout(new GridBagLayout());
60 // text
61 JLabel playerNameLabel = new JLabel("Enter your name: ");
62 playerNameInputElements.add(playerNameLabel);
63 // text field for input
64 playerNameField = new JTextField(20);
65 playerNameInputElements.add(playerNameField);
66 // submit button
67 submitButton = new JButton("Submit");
68 playerNameInputElements.add(submitButton);
69 submitButton.addActionListener(new ActionListener() {
70 public void actionPerformed(ActionEvent event) {
71 String input = playerNameField.getText();
72 welcomeLabel.setText("WELCOME " + input.toUpperCase());
73 frame.setTitle("Tic Tac Toe - Player: " + input);
74 // disable
75 playerNameField.setEnabled(false);
76 submitButton.setEnabled(false);
77 // enable all gameboard buttons
78 Component[] components = gameBoard.getComponents();
79 for (Component component : components) {
80 component.setEnabled(true);
81 }
82 }
83 });
84 // time display
85 // get current system time 24 hr format
86 JLabel timeLabel = new JLabel(getLocalTime());
87 GridBagConstraints c = new GridBagConstraints();
88 c.gridy = 1;
89 bottomPanel.add(timeLabel, c);
90 // update time every second
91 Timer timer = new Timer(1000, new ActionListener() {
92 public void actionPerformed(ActionEvent e) {
93 timeLabel.setText(getLocalTime());
94 }
95 });
96 timer.start();
97 // menu bar
98 JMenuBar menuBar = new JMenuBar();
99 frame.setJMenuBar(menuBar);
100 // menu: control
101 JMenu controlMenu = new JMenu("Control");
102 menuBar.add(controlMenu);
103 JMenuItem exit = new JMenuItem("Exit");
104 exit.addActionListener(new ActionListener() {
105 public void actionPerformed(ActionEvent event) {
106 System.exit(0);
107 }
108 });
109 controlMenu.add(exit);
110 // menu: help
111 JMenu helpMenu = new JMenu("Help");
112 menuBar.add(helpMenu);
113 JMenuItem instruction = new JMenuItem("Instruction");
114 helpMenu.add(instruction);
115 instruction.addActionListener(new ActionListener() {
116 public void actionPerformed(ActionEvent event) {
117 Object[] options = {"Yes"};
118 JOptionPane.showOptionDialog(frame, "Some information about the game:\n"
119 + "- The move is not occupied by any mark.\n"
120 + "- The move is made in the player's turn.\n"
121 + "- The move is made within the 3 x 3 board.\n"
122 + "The game would continue and switch among the player and the computer until it reaches either one of the following conditions:\n"
123 + "- Player wins.\n"
124 + "- Computer wins.\n"
125 + "- Draw.", "Instructions", JOptionPane.DEFAULT_OPTION, JOptionPane.INFORMATION_MESSAGE, null, options, options[0]);
126 }
127 });
128 // the 3x3 game board
129 // is actually buttons?
130 gameBoard = new JPanel();
131 frame.add(gameBoard, BorderLayout.CENTER);
132 gameBoard.setLayout(new GridLayout(3,3));
133 for (int i = 0; i < 9; i++) {
134 JButton button = new JButton();
135 button.setText(" ");
136 // white background
137 button.setBackground(Color.WHITE);
138 // no effect when clicked
139 button.setFocusPainted(false);
140 // disable at beginning
141 button.setEnabled(false);
142 gameBoard.add(button);
143 // actual game logic handling
144 final int const_i = i;
145 button.addActionListener(new ActionListener() {
146 public void actionPerformed(ActionEvent event) {
147 // if button is not empty, do nothing
148 if (button.getText().equals("X") || button.getText().equals("O")) {
149 return;
150 }
151 // player's turn
152 button.setText("X");
153 // set bigger text and green
154 button.setFont(new Font("Arial", Font.BOLD, 40));
155 button.setForeground(Color.GREEN);
156 board[const_i / 3][const_i % 3] = State.PLAYER;
157 board_filled++;
158 // computer's turn
159 welcomeLabel.setText("Valid move, waiting for your opponent.");
160 // check if game is over
161 if (endGameCheck() != END_GAME_STATUS.CONTINUE) {
162 return;
163 }
164 Component[] components = gameBoard.getComponents();
165 // disable all buttons
166 for (Component component : components) {
167 JButton button = (JButton)component;
168 button.setEnabled(false);
169 // set disabled text color to original color
170 button.setUI(new MetalButtonUI() {
171 protected Color getDisabledTextColor() {
172 return button.getForeground();
173 }
174 });
175 }
176 // wait 2 seconds using timer
177 Timer timer = new Timer(2000, new ActionListener() {
178 public void actionPerformed(ActionEvent e) {
179 // find an empty spot by random
180 int x = (int)(Math.random() * 3);
181 int y = (int)(Math.random() * 3);
182 while (board[x][y] != State.EMPTY && board_filled < 9) {
183 x = (int)(Math.random() * 3);
184 y = (int)(Math.random() * 3);
185 }
186 board[x][y] = State.COMPUTER;
187 board_filled++;
188 // update the button
189 int index = x * 3 + y;
190 JButton computerButton = (JButton)components[index];
191 computerButton.setText("O");
192 computerButton.setFont(new Font("Arial", Font.BOLD, 40));
193 computerButton.setForeground(Color.RED);
194 // enable all buttons
195 for (Component component : components) {
196 component.setEnabled(true);
197 }
198 // update top message
199 welcomeLabel.setText("Your opponent has moved, now is your turn.");
200 // check if game is over
201 endGameCheck();
202 }
203 });
204 timer.setRepeats(false);
205 timer.start();
206 }
207 });
208 }
209 // score display on the right
210 scorePanel = new JPanel();
211 scorePanel.setBorder(BorderFactory.createTitledBorder("Score"));
212 frame.add(scorePanel, BorderLayout.EAST);
213 // labels inside the score panel
214 scorePanel.setLayout(new GridBagLayout());
215 GridBagConstraints c2 = new GridBagConstraints();
216 c2.anchor = GridBagConstraints.WEST;
217 c2.ipadx = 30;
218 c2.ipady = 80;
219 // player score
220 JLabel playerScoreText = new JLabel("Player Wins:");
221 c2.gridy = 0;
222 scorePanel.add(playerScoreText, c2);
223 playerScore = new JLabel("0");
224 c2.gridx = 1;
225 scorePanel.add(playerScore, c2);
226 // computer score
227 JLabel computerScoreText = new JLabel("Computer Wins:");
228 c2.gridx = 0;
229 c2.gridy = 1;
230 scorePanel.add(computerScoreText, c2);
231 computerScore = new JLabel("0");
232 c2.gridx = 1;
233 scorePanel.add(computerScore, c2);
234 // draw score
235 JLabel drawScoreText = new JLabel("Draws:");
236 c2.gridx = 0;
237 c2.gridy = 2;
238 scorePanel.add(drawScoreText, c2);
239 drawScore = new JLabel("0");
240 c2.gridx = 1;
241 scorePanel.add(drawScore, c2);
242 // launch the gui
243 frame.setSize(500,500);
244 frame.setVisible(true);
245 }
String getLocalTime()
Get the current system time in 24 hour format.
Definition game.java:251
END_GAME_STATUS endGameCheck()
Responsible for popping a dialog box when the game ends.
Definition game.java:263

References game.State.COMPUTER, game.END_GAME_STATUS.CONTINUE, game.State.EMPTY, endGameCheck(), getLocalTime(), and game.State.PLAYER.

Referenced by main().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ go() [2/2]

void game.go ( )
inline

Initialize the GUI and establish connection to server.

Definition at line 54 of file game.java.

54 {
55 // Initialize empty board
56 for (int i = 0; i < 3; i++) {
57 for (int j = 0; j < 3; j++) {
58 board[i][j] = '\0';
59 }
60 }
61
62 // Setup GUI
63 frame = new JFrame("Tic Tac Toe");
64 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
65
66 // Top display
67 JPanel topPanel = new JPanel();
68 frame.add(topPanel, BorderLayout.NORTH);
69 welcomeLabel = new JLabel("Enter your player name...");
70 topPanel.add(welcomeLabel);
71
72 // Bottom display with name input and time
73 JPanel bottomPanel = new JPanel();
74 bottomPanel.setLayout(new GridBagLayout());
75 frame.add(bottomPanel, BorderLayout.SOUTH);
76
77 // Player name input: holds text, textfield, and submit button
78 JPanel playerNameInputElements = new JPanel();
79 bottomPanel.add(playerNameInputElements);
80 playerNameInputElements.setLayout(new GridBagLayout());
81
82 // Text
83 JLabel playerNameLabel = new JLabel("Enter your name: ");
84 playerNameInputElements.add(playerNameLabel);
85
86 // Text field for input
87 playerNameField = new JTextField(20);
88 playerNameInputElements.add(playerNameField);
89
90 // Submit button
91 submitButton = new JButton("Submit");
92 playerNameInputElements.add(submitButton);
93 submitButton.addActionListener(new ActionListener() {
94 public void actionPerformed(ActionEvent event) {
95 playerName = playerNameField.getText().trim();
96 if (playerName.isEmpty()) {
97 JOptionPane.showMessageDialog(frame, "Name cannot be empty.");
98 return;
99 }
100 submitName();
101 }
102 });
103
104 // Time display
105 JLabel timeLabel = new JLabel(getLocalTime());
106 GridBagConstraints c = new GridBagConstraints();
107 c.gridy = 1;
108 bottomPanel.add(timeLabel, c);
109
110 // Update time every second
111 Timer timer = new Timer(1000, new ActionListener() {
112 public void actionPerformed(ActionEvent e) {
113 timeLabel.setText(getLocalTime());
114 }
115 });
116 timer.start();
117
118 // Menu bar
119 JMenuBar menuBar = new JMenuBar();
120 frame.setJMenuBar(menuBar);
121
122 // Menu: Control
123 JMenu controlMenu = new JMenu("Control");
124 menuBar.add(controlMenu);
125 JMenuItem exit = new JMenuItem("Exit");
126 exit.addActionListener(new ActionListener() {
127 public void actionPerformed(ActionEvent event) {
129 System.exit(0);
130 }
131 });
132 controlMenu.add(exit);
133
134 // Menu: Help
135 JMenu helpMenu = new JMenu("Help");
136 menuBar.add(helpMenu);
137 JMenuItem instruction = new JMenuItem("Instruction");
138 helpMenu.add(instruction);
139 instruction.addActionListener(new ActionListener() {
140 public void actionPerformed(ActionEvent event) {
141 Object[] options = {"Okay"};
142 JOptionPane.showOptionDialog(frame, "Some information about the game:\n\n"
143 + "Criteria for a valid move:\n"
144 + "- The move is not occupied by any mark.\n"
145 + "- The move is made in the player's turn.\n"
146 + "- The move is made within the 3 x 3 board.\n"
147 + "\n"
148 + "The game would continue and switch among the opposite player until it reaches either one of the following conditions:\n"
149 + "- Player 1 wins.\n"
150 + "- Player 2 wins.\n"
151 + "- Draw.\n"
152 + "- One of the players leaves the game.", "Game Information", JOptionPane.DEFAULT_OPTION, JOptionPane.INFORMATION_MESSAGE, null, options, options[0]);
153 }
154 });
155
156 // The 3x3 game board
157 gameBoard = new JPanel();
158 frame.add(gameBoard, BorderLayout.CENTER);
159 gameBoard.setLayout(new GridLayout(3,3));
160 for (int i = 0; i < 9; i++) {
161 JButton button = new JButton();
162 button.setText(" ");
163 // White background
164 button.setBackground(Color.WHITE);
165 // Disable at beginning
166 button.setEnabled(false);
167 gameBoard.add(button);
168 // Actual game logic handling
169 final int const_i = i;
170 button.addActionListener(new ActionListener() {
171 public void actionPerformed(ActionEvent event) {
172 if (!myTurn.get()) {
173 JOptionPane.showMessageDialog(frame, "Not your turn!");
174 return;
175 }
176 if (!button.getText().equals(" ")) {
177 JOptionPane.showMessageDialog(frame, "Cell already occupied!");
178 return;
179 }
180 // Send move to server
181 int row = const_i / 3;
182 int col = const_i % 3;
183 out.println("MOVE " + row + " " + col);
184 }
185 });
186 }
187
188 // Score display on the right
189 scorePanel = new JPanel();
190 scorePanel.setBorder(BorderFactory.createTitledBorder("Score"));
191 frame.add(scorePanel, BorderLayout.EAST);
192 // Labels inside the score panel
193 scorePanel.setLayout(new GridBagLayout());
194 GridBagConstraints c2 = new GridBagConstraints();
195 c2.anchor = GridBagConstraints.WEST;
196 c2.insets = new Insets(5,5,5,5);
197
198 // Player score
199 JLabel player1ScoreText = new JLabel("Player 1 Wins:");
200 c2.gridy = 0;
201 c2.gridx = 0;
202 scorePanel.add(player1ScoreText, c2);
203 player1Score = new JLabel("0");
204 c2.gridx = 1;
205 scorePanel.add(player1Score, c2);
206
207 // Opponent score
208 JLabel player2ScoreText = new JLabel("Player 2 Wins:");
209 c2.gridx = 0;
210 c2.gridy = 1;
211 scorePanel.add(player2ScoreText, c2);
212 player2Score = new JLabel("0");
213 c2.gridx = 1;
214 scorePanel.add(player2Score, c2);
215
216 // Draw score
217 JLabel drawScoreText = new JLabel("Draws:");
218 c2.gridx = 0;
219 c2.gridy = 2;
220 scorePanel.add(drawScoreText, c2);
221 drawScore = new JLabel("0");
222 c2.gridx = 1;
223 scorePanel.add(drawScore, c2);
224
225 // Frame settings
226 frame.setSize(600,600);
227 frame.setVisible(true);
228
229 // Initialize networking
231 }
void closeConnection()
Close the connection to the server.
Definition game.java:529
void initializeConnection()
Establish connection to the server.
Definition game.java:236
void submitName()
Submit the player's name to the server.
Definition game.java:435

References closeConnection(), getLocalTime(), initializeConnection(), and submitName().

Here is the call graph for this function:

◆ initializeConnection()

void game.initializeConnection ( )
inlineprivate

Establish connection to the server.

Definition at line 236 of file game.java.

236 {
237 try {
238 // Connect to the server on localhost
239 socket = new Socket("127.0.0.1", 8901);
240 in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
241 out = new PrintWriter(socket.getOutputStream(), true);
242
243 // Start a thread to listen for messages from the server
244 Thread listener = new Thread(new Runnable() {
245 public void run() {
246 try {
247 String response;
248 while ((response = in.readLine()) != null) {
249 if (response.startsWith("SUBMITNAME")) {
250 // Server requests player to submit name, no action needed here
251 } else if (response.startsWith("INVALIDNAME")) {
252 // Invalid name, prompt user
253 SwingUtilities.invokeLater(new Runnable() {
254 public void run() {
255 JOptionPane.showMessageDialog(frame, "Invalid name submitted. Connection closing.");
257 System.exit(0);
258 }
259 });
260 } else if (response.startsWith("NAMEACCEPTED")) {
261 // Name accepted, wait for both players to join
262 SwingUtilities.invokeLater(new Runnable() {
263 public void run() {
264 welcomeLabel.setText("WELCOME " + playerName);
265 frame.setTitle("Tic Tac Toe - Player: " + playerName.toUpperCase());
266 }
267 });
268 } else if (response.startsWith("GAMESTART")) {
269 String[] parts = response.split(" ");
270 if (parts.length >= 3) {
271 String playerXName = parts[1];
272 String playerOName = parts[2];
273 if (mySymbol == '\0') { // First time receiving GAMESTART
274 if (playerXName.equals(playerName)) {
275 mySymbol = 'X';
276 opponentName = playerOName;
277 } else {
278 mySymbol = 'O';
279 opponentName = playerXName;
280 }
281 if (mySymbol == 'X') {
282 welcomeLabel.setText("Game started. Now is your turn.");
283 myTurn.set(true);
284 enableGameBoard(true);
285 } else {
286 welcomeLabel.setText("WELCOME " + playerName);
287 myTurn.set(false);
288 enableGameBoard(false);
289 }
290 }
291 }
292 } else if (response.startsWith("MOVE")) {
293 String[] parts = response.split(" ");
294 if (parts.length != 4) continue;
295 char symbol = parts[1].charAt(0);
296 int row = Integer.parseInt(parts[2]);
297 int col = Integer.parseInt(parts[3]);
298 SwingUtilities.invokeLater(new Runnable() {
299 public void run() {
300 updateBoard(symbol, row, col);
301 if (symbol != mySymbol) {
302 welcomeLabel.setText("Your opponent has moved. Now is your turn.");
303 myTurn.set(true);
304 enableGameBoard(true);
305 } else {
306 welcomeLabel.setText("Valid move, wait for your opponent.");
307 myTurn.set(false);
308 enableGameBoard(false);
309 }
310 }
311 });
312 } else if (response.startsWith("VICTORY")) {
313 SwingUtilities.invokeLater(new Runnable() {
314 public void run() {
315 int option = JOptionPane.showConfirmDialog(frame, "Congratulations. You wins! Do you want to play again?", "Game Over", JOptionPane.YES_NO_OPTION);
316 if (option == JOptionPane.YES_OPTION) {
317 out.println("RESET");
318 } else {
319 closeConnection();
320 System.exit(0);
321 }
322 if (mySymbol == 'X') {
323 player1Score.setText(Integer.parseInt(player1Score.getText()) + 1 + "");
324 } else {
325 player2Score.setText(Integer.parseInt(player2Score.getText()) + 1 + "");
326 }
327 }
328 });
329 } else if (response.startsWith("DEFEAT")) {
330 SwingUtilities.invokeLater(new Runnable() {
331 public void run() {
332 int option = JOptionPane.showConfirmDialog(frame, "You Lose! Do you want to play again?", "Game Over", JOptionPane.YES_NO_OPTION);
333 if (option == JOptionPane.YES_OPTION) {
334 out.println("RESET");
335 } else {
337 System.exit(0);
338 }
339 if (mySymbol == 'X') {
340 player2Score.setText(Integer.parseInt(player2Score.getText()) + 1 + "");
341 } else {
342 player1Score.setText(Integer.parseInt(player1Score.getText()) + 1 + "");
343 }
344 }
345 });
346 } else if (response.startsWith("TIE")) {
347 SwingUtilities.invokeLater(new Runnable() {
348 public void run() {
349 int option = JOptionPane.showConfirmDialog(frame, "It's a Draw! Do you want to play again?", "Game Over", JOptionPane.YES_NO_OPTION);
350 if (option == JOptionPane.YES_OPTION) {
351 out.println("RESET");
352 } else {
354 System.exit(0);
355 }
356 drawScore.setText(Integer.parseInt(drawScore.getText()) + 1 + "");
357 }
358 });
359 } else if (response.startsWith("YOURMOVE")) {
360 SwingUtilities.invokeLater(new Runnable() {
361 public void run() {
362 welcomeLabel.setText("Your opponent has moved. Now is your turn.");
363 myTurn.set(true);
364 enableGameBoard(true);
365 }
366 });
367 } else if (response.startsWith("WAIT")) {
368 SwingUtilities.invokeLater(new Runnable() {
369 public void run() {
370 welcomeLabel.setText("Valid move, wait for your opponent.");
371 myTurn.set(false);
372 enableGameBoard(false);
373 }
374 });
375 } else if (response.startsWith("MESSAGE")) {
376 String msg = response.substring(8);
377 SwingUtilities.invokeLater(new Runnable() {
378 public void run() {
379 welcomeLabel.setText(msg);
380 }
381 });
382 } else if (response.startsWith("INVALID")) {
383 SwingUtilities.invokeLater(new Runnable() {
384 public void run() {
385 JOptionPane.showMessageDialog(frame, "Invalid Move!");
386 }
387 });
388 } else if (response.startsWith("OTHERLEFT")) {
389 SwingUtilities.invokeLater(new Runnable() {
390 public void run() {
391 JOptionPane.showMessageDialog(frame, "Game Ends. One of the players left.");
392 welcomeLabel.setText("Game started. Wait for your opponent.");
393 resetBoard();
394 enableGameBoard(false);
395 }
396 });
397 } else if (response.startsWith("RESET")) {
398 SwingUtilities.invokeLater(new Runnable() {
399 public void run() {
400 resetBoard();
401 }
402 });
403 } else if (response.startsWith("SERVERFULL")) {
404 SwingUtilities.invokeLater(new Runnable() {
405 public void run() {
406 JOptionPane.showMessageDialog(frame, "Server is full. Try again later.");
408 System.exit(0);
409 }
410 });
411 }
412 }
413 } catch (IOException e) {
414 System.out.println("Connection lost.");
415 SwingUtilities.invokeLater(new Runnable() {
416 public void run() {
417 JOptionPane.showMessageDialog(frame, "Connection to server lost.");
418 resetBoard();
419 }
420 });
421 }
422 }
423 });
424 listener.start();
425
426 } catch (IOException e) {
427 JOptionPane.showMessageDialog(frame, "Cannot connect to the server.");
428 System.exit(0);
429 }
430 }
void enableGameBoard(boolean enable)
Enable or disable the game board buttons based on the player's turn.
Definition game.java:501
void updateBoard(char symbol, int row, int col)
Update the board with the move.
Definition game.java:449
void resetBoard()
Reset the board to start a new game or due to opponent leaving.
Definition game.java:465

References closeConnection(), enableGameBoard(), resetBoard(), and updateBoard().

Referenced by go().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ main() [1/2]

static void game.main ( String[] args)
inlinestatic

Main method to start the game.

Initialize the game board and GUI.

Parameters
argsDoes nothing

Definition at line 29 of file game.java.

29 {
30 game gui = new game();
31 for (int i = 0; i < 3; i++) {
32 for (int j = 0; j < 3; j++) {
33 board[i][j] = State.EMPTY;
34 }
35 }
36 gui.go();
37 }
A simple Tic Tac Toe game with GUI.
Definition game.java:11
void go()
Initialize the GUI.
Definition game.java:43

References game.State.EMPTY, and go().

Here is the call graph for this function:

◆ main() [2/2]

static void game.main ( String[] args)
inlinestatic

Main method to start the game.

Initialize the game board and GUI.

Parameters
argsDoes nothing

Definition at line 42 of file game.java.

42 {
43 game gui = new game();
44 SwingUtilities.invokeLater(new Runnable() {
45 public void run() {
46 gui.go();
47 }
48 });
49 }

References go().

Here is the call graph for this function:

◆ resetBoard()

void game.resetBoard ( )
inlineprivate

Reset the board to start a new game or due to opponent leaving.

Definition at line 465 of file game.java.

465 {
466 board_filled = 0;
467 for (int i = 0; i < 3; i++) {
468 for (int j=0; j <3; j++) {
469 board[i][j] = '\0';
470 }
471 }
472 Component[] components = gameBoard.getComponents();
473 for (Component component : components) {
474 JButton button = (JButton)component;
475 button.setText(" ");
476 button.setEnabled(false);
477 button.setUI(new MetalButtonUI() {
478 protected Color getDisabledTextColor() {
479 return button.getForeground();
480 }
481 });
482 }
483 if (mySymbol == 'X') {
484 welcomeLabel.setText("WELCOME " + playerName + ". Your move.");
485 myTurn.set(true);
486 enableGameBoard(true);
487 } else if (mySymbol == 'O') {
488 welcomeLabel.setText("WELCOME " + playerName + ". Wait for opponent's move.");
489 myTurn.set(false);
490 enableGameBoard(false);
491 } else {
492 // No symbol, possibly due to unsuccessful connection
493 welcomeLabel.setText("Enter your player name...");
494 }
495 }

Referenced by initializeConnection().

Here is the caller graph for this function:

◆ submitName()

void game.submitName ( )
inlineprivate

Submit the player's name to the server.

Definition at line 435 of file game.java.

435 {
436 out.println(playerName);
437 // Update GUI
438 welcomeLabel.setText("Waiting for another player to join...");
439 playerNameField.setEnabled(false);
440 submitButton.setEnabled(false);
441 }

Referenced by go().

Here is the caller graph for this function:

◆ updateBoard()

void game.updateBoard ( char symbol,
int row,
int col )
inlineprivate

Update the board with the move.

Parameters
symbolThe symbol to be placed on the board
rowThe row of the move
colThe column of the move

Definition at line 449 of file game.java.

449 {
450 board[row][col] = symbol;
451 int index = row * 3 + col;
452 JButton button = (JButton)gameBoard.getComponent(index);
453 button.setText(String.valueOf(symbol));
454 button.setFont(new Font("Arial", Font.BOLD, 40));
455 if (symbol == 'X') {
456 button.setForeground(Color.GREEN);
457 } else {
458 button.setForeground(Color.RED);
459 }
460 }

Referenced by initializeConnection().

Here is the caller graph for this function:

The documentation for this class was generated from the following files: