A Tic tac toe program#
def create_board():
return [[' ', ' ', ' '], [' ', ' ', ' '], [' ', ' ', ' ']]
def display_board(board):
board_str = ""
for i in range(0, 3):
board_str += ' '
for j in range(0, 3):
board_str += str(board[i][j])
if j != 2:
board_str += " | "
board_str += '\n'
if i != 2 :
board_str += "-----------\n"
print(board_str)
def evaluate_board(board):
has_empty_cell = False
for i in range(0, 3):
for j in range(0, 3):
if board[i][j] == ' ':
has_empty_cell = True
break
if not has_empty_cell:
return 'Draw'
players = ['X', 'O']
for player in players:
# winning row wise
for i in range(0, 3):
is_winning = True
for j in range(0, 3):
is_winning = is_winning and board[i][j] == player
if is_winning:
return player
# winning column wise
for j in range(0, 3):
is_winning = True
for i in range(0, 3):
is_winning = is_winning and board[i][j] == player
if is_winning:
return player
# winning cross
if board[0][0] == player and board[1][1] == player and board[2][2] == player:
return player
if board[0][2] == player and board[1][1] == player and board[2][0] == player:
return player
return None
def tictactoe(strategy):
board = create_board()
while True:
display_board(board)
row = input("Row: ")
if row == 'q':
break
col = input("Column: ")
if col == 'q':
break
row = int(row)-1
col = int(col)-1
if board[row][col] == ' ':
board[row][col] = 'X'
#display_board(board)
result = evaluate_board(board)
if result:
display_board(board)
print('Winner: ', result)
break
# the machines turn...
best_row, best_col, best_score = strategy(board)
board[best_row][best_col] = 'O'
result = evaluate_board(board)
if result:
display_board(board)
print('Winner: ', result)
break
else:
print('Cell is already taken! Try again...')
print('Exited.')
def copy_board(board):
return [board[0].copy(), board[1].copy(), board[2].copy()]
def strategy_greedy(board):
best_i = None
best_j = None
for i in range(0, 3):
for j in range(0, 3):
if board[i][j] == ' ':
best_i = i
best_j = j
board_o = copy_board(board)
board_o[i][j] = 'O'
result = evaluate_board(board_o)
if result is not None and result == 'O':
return i, j, None
return best_i, best_j, None
#@title
tictactoe(strategy_greedy)
| |
-----------
| |
-----------
| |
---------------------------------------------------------------------------
StdinNotImplementedError Traceback (most recent call last)
Cell In[7], line 2
1 #@title
----> 2 tictactoe(strategy_greedy)
Cell In[4], line 8, in tictactoe(strategy)
4 while True:
6 display_board(board)
----> 8 row = input("Row: ")
9 if row == 'q':
10 break
File ~/env/uni/lib/python3.8/site-packages/ipykernel/kernelbase.py:1190, in Kernel.raw_input(self, prompt)
1188 if not self._allow_stdin:
1189 msg = "raw_input was called, but this frontend does not support input requests."
-> 1190 raise StdinNotImplementedError(msg)
1191 return self._input_request(
1192 str(prompt),
1193 self._parent_ident["shell"],
1194 self.get_parent("shell"),
1195 password=False,
1196 )
StdinNotImplementedError: raw_input was called, but this frontend does not support input requests.
def strategy_one_move(board):
best_i = None
best_j = None
best_score = float('-inf')
# play all possible computation with O and find the most favorable position
for i in range(0, 3):
for j in range(0, 3):
if board[i][j] == ' ':
board_o = copy_board(board)
board_o[i][j] = 'O'
result = evaluate_board(board_o)
if result is not None and result == 'O':
return i, j, 1e6
# play all possible computation with X and compute the score
# the score gives us how favorable the position for O: how many
# winning chances are there and whether the position is lost.
score = 0
for k in range(0, 3):
for l in range(0, 3):
if board_o[k][l] == ' ':
board_x = copy_board(board_o)
board_x[k][l] = 'X'
result = evaluate_board(board_x)
if result is not None:
if (result == 'O'):
score += 1
elif (result == 'Draw'):
score += 0
elif (result == 'X'):
score += -1e6
print(i+1, j+1, score)
if score > best_score:
best_score = score
best_i = i
best_j = j
return best_i, best_j, best_score
tictactoe(strategy_one_move) # play 3,3 -> 2,2 -> 1,3
| |
-----------
| |
-----------
| |
Row: 3
Column: 3
1 1 0
1 2 0
1 3 0
2 1 0
2 2 0
2 3 0
3 1 0
3 2 0
O | |
-----------
| |
-----------
| | X
Row: 2
Column: 2
1 2 0
1 3 0
2 1 0
2 3 0
3 1 0
3 2 0
O | O |
-----------
| X |
-----------
| | X
Row: 1
Column: 3
2 1 -2000000.0
2 3 -1000000.0
3 1 -1000000.0
3 2 -2000000.0
O | O | X
-----------
| X | O
-----------
| | X
Row: 3
Column: 1
O | O | X
-----------
| X | O
-----------
X | | X
Winner: X
Exited.
def strategy_recursive(board, depth=0):
# 1. evaluate position and return if this is an end position
result = evaluate_board(board)
if result is not None:
if (result == 'O'):
return None, None, 1
elif (result == 'Draw'):
return None, None, 0
elif (result == 'X'):
return None, None, -1e6
# 2. expand: play all possible computation with O
best_i = None
best_j = None
best_score = float('-inf')
for i in range(0, 3):
for j in range(0, 3):
if board[i][j] == ' ':
board_o = copy_board(board)
board_o[i][j] = 'O'
result = evaluate_board(board_o)
if result is not None and result == 'O':
return i, j, 1
# play all possible computation with X and compute the score
# the score gives us how favorable the position for O: how many
# winning chances are there and whether the position is lost.
score = 0
for k in range(0, 3):
for l in range(0, 3):
if board_o[k][l] == ' ':
board_x = copy_board(board_o)
board_x[k][l] = 'X'
# Instead of this:
# result = evaluate_board(board_x)
# recursive call to get the score for the next possible moves
_, _, step_score = strategy_recursive(board_x, depth+1)
score += step_score
if depth == 0: # some analytics
print(i+1, j+1, score)
if score > best_score:
best_score = score
best_i = i
best_j = j
return best_i, best_j, best_score
tictactoe(strategy_recursive)
| |
-----------
| |
-----------
| |
Row: q
Exited.
2
2