-
Notifications
You must be signed in to change notification settings - Fork 14
/
TicTacToeClient.java
146 lines (130 loc) · 5.43 KB
/
TicTacToeClient.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
public class TicTacToeClient {
private JFrame frame = new JFrame("Tic Tac Toe");
private JLabel messageLabel = new JLabel("");
private ImageIcon icon;
private ImageIcon opponentIcon;
private Square[] board = new Square[9];
private Square currentSquare;
private static int PORT = 8901;
private Socket socket;
private BufferedReader in;
private PrintWriter out;
// Constructs the client by connecting to a server, laying out the GUI and registering GUI listeners.
public TicTacToeClient(String serverAddress) throws Exception {
// Setup networking
socket = new Socket(serverAddress, PORT);
in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);
// Layout GUI
messageLabel.setBackground(Color.lightGray);
frame.getContentPane().add(messageLabel, "South");
JPanel boardPanel = new JPanel();
boardPanel.setBackground(Color.black);
boardPanel.setLayout(new GridLayout(3, 3, 2, 2));
for (int i = 0; i < board.length; i++) {
final int j = i;
board[i] = new Square();
board[i].addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
currentSquare = board[j];
out.println("MOVE " + j);}});
boardPanel.add(board[i]);
}
frame.getContentPane().add(boardPanel, "Center");
}
//* The main thread of the client will listen for messages from the server.
//The first message will be a "WELCOME" message in which we receive our mark.
//Then we go into a loop listening for:
//--> "VALID_MOVE", --> "OPPONENT_MOVED", --> "VICTORY", --> "DEFEAT", --> "TIE", --> "OPPONENT_QUIT, --> "MESSAGE" messages, and handling each message appropriately.
//The "VICTORY","DEFEAT" and "TIE" ask the user whether or not to play another game.
//If the answer is no, the loop is exited and the server is sent a "QUIT" message. If an OPPONENT_QUIT message is recevied then the loop will exit and the server will be sent a "QUIT" message also.
public void play() throws Exception {
String response;
try {
response = in.readLine();
if (response.startsWith("WELCOME")) {
char mark = response.charAt(8);
icon = new ImageIcon(mark == 'X' ? "x.gif" : "o.gif");
opponentIcon = new ImageIcon(mark == 'X' ? "o.gif" : "x.gif");
frame.setTitle("Tic Tac Toe - Player " + mark);
}
while (true) {
response = in.readLine();
if (response.startsWith("VALID_MOVE")) {
messageLabel.setText("Valid move, please wait");
currentSquare.setIcon(icon);
currentSquare.repaint();
} else if (response.startsWith("OPPONENT_MOVED")) {
int loc = Integer.parseInt(response.substring(15));
board[loc].setIcon(opponentIcon);
board[loc].repaint();
messageLabel.setText("Opponent moved, your turn");
} else if (response.startsWith("VICTORY")) {
messageLabel.setText("You win");
break;
} else if (response.startsWith("DEFEAT")) {
messageLabel.setText("You lose");
break;
} else if (response.startsWith("TIE")) {
messageLabel.setText("You tied");
break;
} else if (response.startsWith("MESSAGE")) {
messageLabel.setText(response.substring(8));
}
}
out.println("QUIT");
}
finally {
socket.close();
}
}
private boolean wantsToPlayAgain() {
int response = JOptionPane.showConfirmDialog(frame,
"Want to play again?",
"Tic Tac Toe is Fun Fun Fun",
JOptionPane.YES_NO_OPTION);
frame.dispose();
return response == JOptionPane.YES_OPTION;
}
//Graphical square in the client window.
static class Square extends JPanel {
JLabel label = new JLabel((Icon)null);
public Square() {
setBackground(Color.white);
add(label);
}
public void setIcon(Icon icon) {
label.setIcon(icon);
}
}
//main
public static void main(String[] args) throws Exception {
while (true) {
String serverAddress = (args.length == 0) ? "localhost" : args[1];
TicTacToeClient client = new TicTacToeClient(serverAddress);
client.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
client.frame.setSize(240, 160);
client.frame.setVisible(true);
client.frame.setResizable(false);
client.play();
if (!client.wantsToPlayAgain()) {
break;
}
}
}
}