Spaces:
Sleeping
Sleeping
Upload 2 files
Browse files- requirements.txt +1 -0
- tictactoe.py +126 -0
requirements.txt
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
pygame
|
tictactoe.py
ADDED
@@ -0,0 +1,126 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""
|
2 |
+
Tic Tac Toe Player
|
3 |
+
"""
|
4 |
+
|
5 |
+
import math
|
6 |
+
|
7 |
+
X = "X"
|
8 |
+
O = "O"
|
9 |
+
EMPTY = None
|
10 |
+
|
11 |
+
|
12 |
+
def initial_state():
|
13 |
+
"""
|
14 |
+
Returns starting state of the board.
|
15 |
+
"""
|
16 |
+
return [[EMPTY, EMPTY, EMPTY],
|
17 |
+
[EMPTY, EMPTY, EMPTY],
|
18 |
+
[EMPTY, EMPTY, EMPTY]]
|
19 |
+
|
20 |
+
|
21 |
+
def player(board):
|
22 |
+
"""
|
23 |
+
Returns player who has the next turn on a board.
|
24 |
+
"""
|
25 |
+
x_count = sum(row.count(X) for row in board)
|
26 |
+
o_count = sum(row.count(O) for row in board)
|
27 |
+
return X if x_count == o_count else O
|
28 |
+
|
29 |
+
|
30 |
+
def actions(board):
|
31 |
+
"""
|
32 |
+
Returns set of all possible actions (i, j) available on the board.
|
33 |
+
"""
|
34 |
+
return {(i, j) for i in range(3) for j in range(3) if board[i][j] == EMPTY}
|
35 |
+
|
36 |
+
|
37 |
+
def result(board, action):
|
38 |
+
"""
|
39 |
+
Returns the board that results from making move (i, j) on the board.
|
40 |
+
"""
|
41 |
+
if board[action[0]][action[1]] is not EMPTY:
|
42 |
+
raise Exception("Invalid action")
|
43 |
+
|
44 |
+
new_board = [row[:] for row in board]
|
45 |
+
new_board[action[0]][action[1]] = player(board)
|
46 |
+
return new_board
|
47 |
+
|
48 |
+
|
49 |
+
def winner(board):
|
50 |
+
"""
|
51 |
+
Returns the winner of the game, if there is one.
|
52 |
+
"""
|
53 |
+
for line in board: # Check rows
|
54 |
+
if line[0] == line[1] == line[2] and line[0] is not None:
|
55 |
+
return line[0]
|
56 |
+
for col in range(3): # Check columns
|
57 |
+
if board[0][col] == board[1][col] == board[2][col] and board[0][col] is not None:
|
58 |
+
return board[0][col]
|
59 |
+
if board[0][0] == board[1][1] == board[2][2] and board[0][0] is not None: # Check diagonal
|
60 |
+
return board[0][0]
|
61 |
+
if board[0][2] == board[1][1] == board[2][0] and board[0][2] is not None: # Check anti-diagonal
|
62 |
+
return board[0][2]
|
63 |
+
return None
|
64 |
+
|
65 |
+
|
66 |
+
def terminal(board):
|
67 |
+
"""
|
68 |
+
Returns True if game is over, False otherwise.
|
69 |
+
"""
|
70 |
+
return winner(board) is not None or all(cell is not EMPTY for row in board for cell in row)
|
71 |
+
|
72 |
+
|
73 |
+
def utility(board):
|
74 |
+
"""
|
75 |
+
Returns 1 if X has won the game, -1 if O has won, 0 otherwise.
|
76 |
+
"""
|
77 |
+
win = winner(board)
|
78 |
+
if win == X:
|
79 |
+
return 1
|
80 |
+
elif win == O:
|
81 |
+
return -1
|
82 |
+
else:
|
83 |
+
return 0
|
84 |
+
|
85 |
+
|
86 |
+
def minimax(board):
|
87 |
+
"""
|
88 |
+
Returns the optimal action for the current player on the board.
|
89 |
+
"""
|
90 |
+
if terminal(board):
|
91 |
+
return None
|
92 |
+
|
93 |
+
turn = player(board)
|
94 |
+
|
95 |
+
def max_value(board):
|
96 |
+
if terminal(board):
|
97 |
+
return utility(board), None
|
98 |
+
v = -math.inf
|
99 |
+
best_move = None
|
100 |
+
for action in actions(board):
|
101 |
+
val, _ = min_value(result(board, action))
|
102 |
+
if val > v:
|
103 |
+
v = val
|
104 |
+
best_move = action
|
105 |
+
return v, best_move
|
106 |
+
|
107 |
+
def min_value(board):
|
108 |
+
if terminal(board):
|
109 |
+
return utility(board), None
|
110 |
+
v = math.inf
|
111 |
+
best_move = None
|
112 |
+
for action in actions(board):
|
113 |
+
val, _ = max_value(result(board, action))
|
114 |
+
if val < v:
|
115 |
+
v = val
|
116 |
+
best_move = action
|
117 |
+
return v, best_move
|
118 |
+
|
119 |
+
if turn == X:
|
120 |
+
_, move = max_value(board)
|
121 |
+
else:
|
122 |
+
_, move = min_value(board)
|
123 |
+
|
124 |
+
return move
|
125 |
+
|
126 |
+
|