1
+ '''
2
+ TIC-TAC-TOE GAME USING MINIMAX ALGORITHM
3
+
4
+ Minimax is a kind of backtracking algorithm. It searches, recursively, the
5
+ best move that leads the Max player to win or not lose (draw). It considers
6
+ the current state of the game and the available moves at that state, then
7
+ for each valid move, it plays (alternating min and max) until it finds a
8
+ terminal state (win, draw or lose).
9
+
10
+ '''
11
+
12
+ #Import the necessary libraries
13
+ import numpy as np
14
+ from math import inf as infinity
15
+
16
+ #Set the Empty Board
17
+ game_state = [[' ' ,' ' ,' ' ],
18
+ [' ' ,' ' ,' ' ],
19
+ [' ' ,' ' ,' ' ]]
20
+ #Create the Two Players as 'X'/'O'
21
+ players = ['X' ,'O' ]
22
+
23
+ #Method for checking the correct move on Tic-Tac-Toe
24
+ def play_move (state , player , block_num ):
25
+ if state [int ((block_num - 1 )/ 3 )][(block_num - 1 )% 3 ] is ' ' :
26
+
27
+ state [int ((block_num - 1 )/ 3 )][(block_num - 1 )% 3 ] = player
28
+ else :
29
+ block_num = int (input ("Block is not empty, ya blockhead! Choose again: " ))
30
+ play_move (state , player , block_num )
31
+
32
+ #Method to copy the current game state to new_state of Tic-Tac-Toe
33
+ def copy_game_state (state ):
34
+ new_state = [[' ' ,' ' ,' ' ],[' ' ,' ' ,' ' ],[' ' ,' ' ,' ' ]]
35
+ for i in range (3 ):
36
+ for j in range (3 ):
37
+ new_state [i ][j ] = state [i ][j ]
38
+ return new_state
39
+
40
+ #Method to check the current state of the Tic-Tac-Toe
41
+ def check_current_state (game_state ):
42
+
43
+ # Check horizontals in first row
44
+ if (game_state [0 ][0 ] == game_state [0 ][1 ] and game_state [0 ][1 ] == game_state [0 ][2 ] and game_state [0 ][0 ] is not ' ' ):
45
+ return game_state [0 ][0 ], "Done"
46
+ # Check horizontals in second row
47
+ if (game_state [1 ][0 ] == game_state [1 ][1 ] and game_state [1 ][1 ] == game_state [1 ][2 ] and game_state [1 ][0 ] is not ' ' ):
48
+ return game_state [1 ][0 ], "Done"
49
+ # Check horizontals in third row
50
+ if (game_state [2 ][0 ] == game_state [2 ][1 ] and game_state [2 ][1 ] == game_state [2 ][2 ] and game_state [2 ][0 ] is not ' ' ):
51
+ return game_state [2 ][0 ], "Done"
52
+
53
+ # Check verticals in first column
54
+ if (game_state [0 ][0 ] == game_state [1 ][0 ] and game_state [1 ][0 ] == game_state [2 ][0 ] and game_state [0 ][0 ] is not ' ' ):
55
+ return game_state [0 ][0 ], "Done"
56
+ # Check verticals in second column
57
+ if (game_state [0 ][1 ] == game_state [1 ][1 ] and game_state [1 ][1 ] == game_state [2 ][1 ] and game_state [0 ][1 ] is not ' ' ):
58
+ return game_state [0 ][1 ], "Done"
59
+ # Check verticals in third column
60
+ if (game_state [0 ][2 ] == game_state [1 ][2 ] and game_state [1 ][2 ] == game_state [2 ][2 ] and game_state [0 ][2 ] is not ' ' ):
61
+ return game_state [0 ][2 ], "Done"
62
+
63
+ # Check left diagonal
64
+ if (game_state [0 ][0 ] == game_state [1 ][1 ] and game_state [1 ][1 ] == game_state [2 ][2 ] and game_state [1 ][1 ] is not ' ' ):
65
+ return game_state [1 ][1 ], "Done"
66
+ # Check right diagonal
67
+ if (game_state [0 ][2 ] == game_state [1 ][1 ] and game_state [1 ][1 ] == game_state [2 ][0 ] and game_state [0 ][2 ] is not ' ' ):
68
+ return game_state [1 ][1 ], "Done"
69
+
70
+ draw_flag = 0
71
+ for i in range (3 ):
72
+ for j in range (3 ):
73
+ if game_state [i ][j ] is ' ' :
74
+ draw_flag = 1
75
+ if draw_flag is 0 :
76
+ return None , "Draw"
77
+
78
+ return None , "Not Done"
79
+
80
+ #Method to print the Tic-Tac-Toe Board
81
+ def print_board (game_state ):
82
+ print ('----------------' )
83
+ print ('| ' + str (game_state [0 ][0 ]) + ' || ' + str (game_state [0 ][1 ]) + ' || ' + str (game_state [0 ][2 ]) + ' |' )
84
+ print ('----------------' )
85
+ print ('| ' + str (game_state [1 ][0 ]) + ' || ' + str (game_state [1 ][1 ]) + ' || ' + str (game_state [1 ][2 ]) + ' |' )
86
+ print ('----------------' )
87
+ print ('| ' + str (game_state [2 ][0 ]) + ' || ' + str (game_state [2 ][1 ]) + ' || ' + str (game_state [2 ][2 ]) + ' |' )
88
+ print ('----------------' )
89
+
90
+ #Method for implement the Minimax Algorithm
91
+ def getBestMove (state , player ):
92
+ winner_loser , done = check_current_state (state )
93
+
94
+ # Checking condition for winner, if winner_loser is 'O' then Computer won
95
+ # else if winner_loser is 'X' then You won else game is draw
96
+ if done == "Done" and winner_loser == 'O' :
97
+ return 1 # for computer
98
+ elif done == "Done" and winner_loser == 'X' :
99
+ return - 1 # for player
100
+ elif done == "Draw" :
101
+ return 0
102
+
103
+ moves = []
104
+ empty_cells = []
105
+
106
+ #Append the block_num to the empty_cells list
107
+ for i in range (3 ):
108
+ for j in range (3 ):
109
+ if state [i ][j ] is ' ' :
110
+ empty_cells .append (i * 3 + (j + 1 ))
111
+
112
+ for empty_cell in empty_cells :
113
+ move = {}
114
+
115
+ move ['index' ] = empty_cell
116
+
117
+ #Call the copy_game_state method
118
+ new_state = copy_game_state (state )
119
+ \
120
+ play_move (new_state , player , empty_cell )
121
+
122
+ #if player is computer
123
+ if player == 'O' :
124
+ result = getBestMove (new_state ,'X' )
125
+ move ['score' ] = result
126
+ else :
127
+ result = getBestMove (new_state ,'O' )
128
+ move ['score' ] = result
129
+
130
+ moves .append (move )
131
+
132
+ # Find best move
133
+ best_move = None
134
+ #Check if player is computer('O')
135
+ if player == 'O' :
136
+ best = - infinity
137
+ for move in moves :
138
+ if move ['score' ]> best :
139
+ best = move ['score' ]
140
+ best_move = move ['index' ]
141
+ else :
142
+ best = infinity
143
+ for move in moves :
144
+ if move ['score' ]< best :
145
+ best = move ['score' ]
146
+ best_move = move ['index' ]
147
+
148
+ return best_move
149
+
150
+ # Now PLaying the Tic-Tac-Toe Game
151
+ play_again = 'Y'
152
+ while play_again == 'Y' or play_again == 'y' :
153
+ #Set the empty board for Tic-Tac-Toe
154
+ game_state = [[' ' ,' ' ,' ' ],
155
+ [' ' ,' ' ,' ' ],
156
+ [' ' ,' ' ,' ' ]]
157
+ #Set current_state as "Not Done"
158
+ current_state = "Not Done"
159
+ print ("\n New Game!" )
160
+
161
+ #print the game_state
162
+ print_board (game_state )
163
+
164
+ #Select the player_choice to start the game
165
+ player_choice = input ("Choose which player goes first - X(You) or O(Computer): " )
166
+
167
+ #Set winner as None
168
+ winner = None
169
+
170
+ #if player_choice is ('X' or 'x') for humans else for computer
171
+ if player_choice == 'X' or player_choice == 'x' :
172
+ current_player_idx = 0
173
+ else :
174
+ current_player_idx = 1
175
+
176
+ while current_state == "Not Done" :
177
+ #For Human Turn
178
+ if current_player_idx == 0 :
179
+ block_choice = int (input ("Your turn please! Choose where to place (1 to 9): " ))
180
+ play_move (game_state , players [current_player_idx ], block_choice )
181
+ else : # Computer turn
182
+ block_choice = getBestMove (game_state , players [current_player_idx ])
183
+ play_move (game_state , players [current_player_idx ], block_choice )
184
+ print ("AI plays move: " + str (block_choice ))
185
+ print_board (game_state )
186
+ winner , current_state = check_current_state (game_state )
187
+ if winner is not None :
188
+ print (str (winner ) + " won!" )
189
+ else :
190
+ current_player_idx = (current_player_idx + 1 )% 2
191
+
192
+ if current_state is "Draw" :
193
+ print ("Draw!" )
194
+
195
+ play_again = input ('Wanna try again?(Y/N) : ' )
196
+ if play_again == 'N' :
197
+ print ('Thank you for playing Tic-Tac-Toe Game!!!!!!!' )
198
+
199
+ '''
200
+ Sample woking:
201
+
202
+ New Game!
203
+ ----------------
204
+ | || || |
205
+ ----------------
206
+ | || || |
207
+ ----------------
208
+ | || || |
209
+ ----------------
210
+
211
+ Choose which player goes first - X(You) or O(Computer): X
212
+
213
+ Your turn please! Choose where to place (1 to 9): 3
214
+ ----------------
215
+ | || || X |
216
+ ----------------
217
+ | || || |
218
+ ----------------
219
+ | || || |
220
+ ----------------
221
+ AI plays move: 2
222
+ ----------------
223
+ | || O || X |
224
+ ----------------
225
+ | || || |
226
+ ----------------
227
+ | || || |
228
+ ----------------
229
+
230
+ Your turn please! Choose where to place (1 to 9): 7
231
+ ----------------
232
+ | || O || X |
233
+ ----------------
234
+ | || || |
235
+ ----------------
236
+ | X || || |
237
+ ----------------
238
+ AI plays move: 1
239
+ ----------------
240
+ | O || O || X |
241
+ ----------------
242
+ | || || |
243
+ ----------------
244
+ | X || || |
245
+ ----------------
246
+
247
+ Your turn please! Choose where to place (1 to 9): 5
248
+ ----------------
249
+ | O || O || X |
250
+ ----------------
251
+ | || X || |
252
+ ----------------
253
+ | X || || |
254
+ ----------------
255
+ X won!
256
+
257
+ Wanna try again?(Y/N) : n
258
+
259
+ '''
0 commit comments