1 import java.io.*;
2 import java.net.*;
3 import java.util.Date;
4 import javafx.application.Application;
5 import javafx.application.Platform;
6 import javafx.scene.Scene;
7 import javafx.scene.control.ScrollPane;
8 import javafx.scene.control.TextArea;
9 import javafx.stage.Stage;
10
11 public class TicTacToeServer extends Application
12 implements TicTacToeConstants {
13 private int sessionNo = 1;
14
15 @Override
16 public void start(Stage primaryStage) {
17 TextArea taLog = new TextArea();
18
19
20 Scene scene = new Scene(new ScrollPane(taLog), 450, 200);
21 primaryStage.setTitle("TicTacToeServer");
22 primaryStage.setScene(scene);
23 primaryStage.show();
24
25 new Thread( () -> {
26 try {
27
28 ServerSocket serverSocket = new ServerSocket(8000);
29 Platform.runLater(() -> taLog.appendText(new Date() +
30 ": Server started at socket 8000\n"));
31
32
33 while (true) {
34 Platform.runLater(() -> taLog.appendText(new Date() +
35 ": Wait for players to join session " + sessionNo + '\n'));
36
37
38 Socket player1 = serverSocket.accept();
39
40 Platform.runLater(() -> {
41 taLog.appendText(new Date() + ": Player 1 joined session "
42 + sessionNo + '\n');
43 taLog.appendText("Player 1's IP address" +
44 player1.getInetAddress().getHostAddress() + '\n');
45 });
46
47
48 new DataOutputStream(
49 player1.getOutputStream()).writeInt(PLAYER1);
50
51
52 Socket player2 = serverSocket.accept();
53
54 Platform.runLater(() -> {
55 taLog.appendText(new Date() +
56 ": Player 2 joined session " + sessionNo + '\n');
57 taLog.appendText("Player 2's IP address" +
58 player2.getInetAddress().getHostAddress() + '\n');
59 });
60
61
62 new DataOutputStream(
63 player2.getOutputStream()).writeInt(PLAYER2);
64
65
66 Platform.runLater(() ->
67 taLog.appendText(new Date() +
68 ": Start a thread for session " + sessionNo++ + '\n'));
69
70
71 new Thread(new HandleASession(player1, player2)).start();
72 }
73 }
74 catch(IOException ex) {
75 ex.printStackTrace();
76 }
77 }).start();
78 }
79
80
81 class HandleASession implements Runnable, TicTacToeConstants {
82 private Socket player1;
83 private Socket player2;
84
85
86 private char[][] cell = new char[3][3];
87
88 private DataInputStream fromPlayer1;
89 private DataOutputStream toPlayer1;
90 private DataInputStream fromPlayer2;
91 private DataOutputStream toPlayer2;
92
93
94 private boolean continueToPlay = true;
95
96
97 public HandleASession(Socket player1, Socket player2) {
98 this.player1 = player1;
99 this.player2 = player2;
100
101
102 for (int i = 0; i < 3; i++)
103 for (int j = 0; j < 3; j++)
104 cell[i][j] = ' ';
105 }
106
107
108 public void run() {
109 try {
110
111 DataInputStream fromPlayer1 = new DataInputStream(
112 player1.getInputStream());
113 DataOutputStream toPlayer1 = new DataOutputStream(
114 player1.getOutputStream());
115 DataInputStream fromPlayer2 = new DataInputStream(
116 player2.getInputStream());
117 DataOutputStream toPlayer2 = new DataOutputStream(
118 player2.getOutputStream());
119
120
121
122 toPlayer1.writeInt(1);
123
124
125
126 while (true) {
127
128 int row = fromPlayer1.readInt();
129 int column = fromPlayer1.readInt();
130 cell[row][column] = 'X';
131
132
133 if (isWon('X')) {
134 toPlayer1.writeInt(PLAYER1_WON);
135 toPlayer2.writeInt(PLAYER1_WON);
136 sendMove(toPlayer2, row, column);
137 break;
138 }
139 else if (isFull()) {
140 toPlayer1.writeInt(DRAW);
141 toPlayer2.writeInt(DRAW);
142 sendMove(toPlayer2, row, column);
143 break;
144 }
145 else {
146
147 toPlayer2.writeInt(CONTINUE);
148
149
150 sendMove(toPlayer2, row, column);
151 }
152
153
154 row = fromPlayer2.readInt();
155 column = fromPlayer2.readInt();
156 cell[row][column] = 'O';
157
158
159 if (isWon('O')) {
160 toPlayer1.writeInt(PLAYER2_WON);
161 toPlayer2.writeInt(PLAYER2_WON);
162 sendMove(toPlayer1, row, column);
163 break;
164 }
165 else {
166
167 toPlayer1.writeInt(CONTINUE);
168
169
170 sendMove(toPlayer1, row, column);
171 }
172 }
173 }
174 catch(IOException ex) {
175 ex.printStackTrace();
176 }
177 }
178
179
180 private void sendMove(DataOutputStream out, int row, int column)
181 throws IOException {
182 out.writeInt(row);
183 out.writeInt(column);
184 }
185
186
187 private boolean isFull() {
188 for (int i = 0; i < 3; i++)
189 for (int j = 0; j < 3; j++)
190 if (cell[i][j] == ' ')
191 return false;
192
193
194 return true;
195 }
196
197
198 private boolean isWon(char token) {
199
200 for (int i = 0; i < 3; i++)
201 if ((cell[i][0] == token)
202 && (cell[i][1] == token)
203 && (cell[i][2] == token)) {
204 return true;
205 }
206
207
208 for (int j = 0; j < 3; j++)
209 if ((cell[0][j] == token)
210 && (cell[1][j] == token)
211 && (cell[2][j] == token)) {
212 return true;
213 }
214
215
216 if ((cell[0][0] == token)
217 && (cell[1][1] == token)
218 && (cell[2][2] == token)) {
219 return true;
220 }
221
222
223 if ((cell[0][2] == token)
224 && (cell[1][1] == token)
225 && (cell[2][0] == token)) {
226 return true;
227 }
228
229
230 return false;
231 }
232 }
233
234
238 public static void main(String[] args) {
239 launch(args);
240 }
241 }