-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathTicTacToe.java
More file actions
327 lines (276 loc) · 8.65 KB
/
TicTacToe.java
File metadata and controls
327 lines (276 loc) · 8.65 KB
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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
// Strategy pattern.
// The computer player's behavior/strategy can be replaced by inheriting from the interface below
// Also, the human player's behavior inherits from the same interface
// This also makes it easy to modify the game for 2 human players, 2 computer players etc.
interface MoveMethod
{
public int move();
}
class SimpleMoveStrategy implements MoveMethod
{
private TicTacToe game;
public SimpleMoveStrategy(TicTacToe t) {
game = t ;
}
public int move() {
for( int i = 0 ; i < TicTacToe.N ; i ++ )
{
for( int j = 0 ; j < TicTacToe.N ; j ++ )
{
if( game.board[i][j] == 0 )
return (i*3+j+1) ;
}
}
return 0 ;
}
}
class HumanMove implements MoveMethod
{
private TicTacToe game;
public HumanMove(TicTacToe t) {
game = t ;
}
public int move() {
String move_str ;
int move_int = 0 ;
boolean valid_input = false ;
while(!valid_input) {
System.out.print("Where to ? ");
move_str = TicTacToe.getUserInput() ;
if( Character.isDigit(move_str.toCharArray()[0]) ) {
move_int = Integer.parseInt(move_str);
if( ( move_int <= (TicTacToe.N)*(TicTacToe.N) ) && move_int >= 1 ) {
valid_input = true ;
break ;
}
}
if( !valid_input ) {
System.out.println("Invalid input");
continue ;
}
}
return move_int ;
}
}
class TicTacToe
{
protected static final int N = 3 ;
private static final int HSPACE = 20 ;
protected int[][] board;
private static BufferedReader reader =
new BufferedReader(new InputStreamReader(System.in)) ;
class Player
{
private String name ;
private int player_type ;
private int player_order ;
private MoveMethod move_strategy ;
public Player(String pname, int type, int order, MoveMethod move_s )
{
name = pname ;
player_type = type ;
player_order = order ;
move_strategy = move_s ;
}
public String getName() {
return name ;
}
public int getPlayerType() {
return player_type ;
}
public int getMove() {
return move_strategy.move();
}
}
private Player player1,player2;
public Player getplayer1() {
return player1 ;
}
public Player getplayer2() {
return player2 ;
}
public static String getPosDescription(int pos) {
String str = "";
if( pos == 5 ) {
str = "center" ;
return str ;
}
if( (pos-1)/3 == 0 ) {
str += "upper " ;
}
else if( (pos-1)/3 == 1 ) {
str += "middle " ;
}
else
str += "lower " ;
if( (pos-1) % 3 == 0 )
str += "left" ;
else if( (pos-1)%3 == 1 )
str += "middle" ;
else
str += "right" ;
return str ;
}
protected static String getUserInput() {
String input = "" ;
try {
input = reader.readLine();
} catch (IOException ex) {
ex.printStackTrace();
}
return input ;
}
public TicTacToe()
{
board = new int[N][N];
for( int i = 0 ; i < N ; i ++ ) {
for( int j = 0 ; j < N ; j ++ ) {
board[i][j] = 0 ;
}
}
System.out.println("Enter player name");
player1 = new Player(getUserInput(),2,0,new HumanMove(this));
player2 = new Player("",1,1,new SimpleMoveStrategy(this));
System.out.println("\nHuman player " + player1.getName() + " vs Computer Player " + player2.getName() + ":" ) ;
}
public boolean setMove(int move, int p_type)
{
int x_coord = (move-1)/3;
int y_coord = (move-1)%3;
if( board[x_coord][y_coord] == 0 )
{
board[x_coord][y_coord] = p_type ;
return true ;
}
else
{
System.out.println("Invalid move");
return false ;
}
}
private enum WinConfig {
DRAW, WIN, NONE
}
private WinConfig isWinningConfig()
{
WinConfig w = WinConfig.WIN ;
// rows
for( int i = 0 ; i < N ; i ++ )
{
if( (board[i][0] != 0) && (board[i][0] == board[i][1]) && (board[i][0] == board[i][2] ) )
{
return w ;
}
}
// columns
for( int i = 0 ; i < N ; i ++ )
{
if( (board[0][i] != 0) && (board[0][i] == board[1][i]) && (board[0][i] == board[2][i] ) )
{
return w ;
}
}
// diags
if( (board[0][0] != 0) && (board[0][0] == board[1][1]) && (board[0][0] == board[2][2] ) )
{
return w ;
}
if( (board[2][0] != 0) && (board[2][0] == board[1][1]) && (board[2][0] == board[0][2] ) )
{
return w ;
}
// draw
w = WinConfig.DRAW ;
for( int i = 0 ; i < N ; i ++ )
for( int j = 0 ; j < N ; j ++ )
{
if( board[i][j] == 0 )
w = WinConfig.NONE ;
}
return w ;
}
private String getRowString(int row)
{
String s = "" ;
for( int i = 0 ; i < N ; i ++ )
{
switch(board[row][i]) {
case 0: s += " " ;
break ;
case 1: s += "O" ;
break ;
case 2: s += "X" ;
}
if( i != N-1 )
{
s += " | " ;
}
}
s += String.format("%" + HSPACE + "s", "");
for( int i = 0 ; i < N ; i ++ )
{
s += row*3+i+1 ;
if( i == N-1 ) {
s += "\n";
}
else {
s += " | " ;
}
}
return s;
}
public String toString()
{
String s = "";
// iterate through the rows
for( int i = 0 ; i < N ; i ++ ) {
s += getRowString(i);
}
return s;
}
public static void main( String[] args )
{
System.out.println("Welcome to Tic-Tac-Toe.");
System.out.println("");
TicTacToe game = new TicTacToe();
String move_str ;
int move1 = 0 ;
int move2 = 0 ;
int player_type = 0 ;
WinConfig w = WinConfig.NONE ;
System.out.println("Please make your move selection by entering a number 1-9 corresponding to the movement key on the right.\n");
System.out.println(game.toString()) ;
while( game.isWinningConfig() == WinConfig.NONE )
{
do {
move1 = game.getplayer1().getMove();
} while(!game.setMove(move1,game.getplayer1().getPlayerType() ));
if( ( w = game.isWinningConfig() ) == WinConfig.WIN ) {
System.out.println("");
System.out.println(game.toString() );
System.out.println("You have beaten my poor AI!");
break ;
}
else if( w == WinConfig.DRAW ) {
System.out.println("");
System.out.println(game.toString()) ;
System.out.println("Well played. It is a draw!");
break ;
}
move2 = game.getplayer2().getMove();
System.out.println("");
System.out.println("You have put an X in the " + TicTacToe.getPosDescription(move1) + ". I will put a O in the " + TicTacToe.getPosDescription(move2) + "." ) ;
game.setMove(move2, game.getplayer2().getPlayerType() ) ;
if( game.isWinningConfig() == WinConfig.WIN ) {
System.out.println("");
System.out.println(game.toString() );
System.out.println("I won. Thanks for playing.") ;
break ;
}
System.out.println(game.toString());
}
}
}