import numpy as np
n = 3
points = {"X": +1, "E": 0, "O": -1}
def print_board(board_state):
for i in range(n):
print(" ".join(board_state[i*n:(i+1)*n]))
print("-"*10)
# returns X if X has won, O if O has won, TIE if it is a tie, and NONE if the game is still in progress
def board_value(board_state):
for i in range(n):
horizontal_ct = 0
vertical_ct = 0
for j in range(n):
horizontal_ct += points[board_state[i*n + j]]
vertical_ct += points[board_state[j*n + i]]
if horizontal_ct == n or vertical_ct == n:
return "X"
if horizontal_ct == -n or vertical_ct == -n:
return "O"
diagonal_down = 0
diagonal_up = 0
for i in range(3):
diagonal_down += points[board_state[i*n+i]]
diagonal_up += points[board_state[(n-i-1)*n+i]]
for i in range(9):
if board_state[i] == "E":
return "NONE"
return "TIE"
# returns winner ("X" or "O")
# note: cheaters never win
def play_game(strategyX, strategyO):
board_state = ["E" for i in range(n**2)]
while board_value(board_state) == "NONE":
for player, strategy in (("X", strategyX), ("O", strategyO)):
other_player = "O" if player == "X" else "X"
old_board_state = board_state[:]
print_board(board_state)
move = strategy(board_state, player)
print(f"^(move = {player}({board_state}))", strategy)
if board_state[move] != "E" or board_state != old_board_state or not (0 <= move < n**2):
print(f"{player} is a CHEATER, tried move={move}")
return other_player
board_state[move] = player
if board_value(board_state) != "NONE":
# print_board(board_state)
return board_value(board_state)
#### strategies:
def ziyong_computer_move(boardState, player):
other_player = "O" if player == "X" else "X"
# check for moves that can win the game
for i in range(3):
if (boardState[i] == boardState[i + 3] == player):
if (boardState[i + 6] == "E"):
return i + 6
if (boardState[i + 3] == boardState[i + 6] == player):
if (boardState[i] == "E"):
return i
if (boardState[i] == boardState[i + 6] == player):
if (boardState[i + 3] == "E"):
return i + 3
if (boardState[i * 3] == boardState[i * 3 + 1] == player):
if (boardState[i * 3 + 2] == "E"):
return i * 3 + 2
if (boardState[i * 3 + 1] == boardState[i * 3 + 2] == player):
if (boardState[i * 3] == "E"):
return i * 3
if (boardState[i * 3] == boardState[i * 3 + 2] == player):
if (boardState[i * 3 + 1] == "E"):
return i * 3 + 1
if (boardState[0] == boardState[4] == player):
if (boardState[8] == "E"):
return 8
if (boardState[0] == boardState[8] == player):
if (boardState[4] == "E"):
return 4
if (boardState[4] == boardState[8] == player):
if (boardState[0] == "E"):
return 0
if (boardState[2] == boardState[4] == player):
if (boardState[6] == "E"):
return 6
if (boardState[2] == boardState[6] == player):
if (boardState[4] == "E"):
return 4
if (boardState[6] == boardState[4] == player):
if (boardState[2] == "E"):
return 2
# checking for moves that can lose the game
for i in range(3):
if (boardState[i] == boardState[i + 3] == other_player):
if (boardState[i + 6] == "E"):
return i + 6
if (boardState[i + 3] == boardState[i + 6] == other_player):
if (boardState[i] == "E"):
return i
if (boardState[i] == boardState[i + 6] == other_player):
if (boardState[i + 3] == "E"):
return i + 3
if (boardState[i * 3] == boardState[i * 3 + 1] == other_player):
if (boardState[i * 3 + 2] == "E"):
return i * 3 + 2
if (boardState[i * 3 + 1] == boardState[i * 3 + 2] == other_player):
if (boardState[i * 3] == "E"):
return i * 3
if (boardState[i * 3] == boardState[i * 3 + 2] == other_player):
if (boardState[i * 3 + 1] == "E"):
return i * 3 + 1
if (boardState[0] == boardState[4] == other_player):
if (boardState[8] == "E"):
return 8
if (boardState[0] == boardState[8] == other_player):
if (boardState[4] == "E"):
return 4
if (boardState[4] == boardState[8] == other_player):
if (boardState[0] == "E"):
return 0
if (boardState[2] == boardState[4] == other_player):
if (boardState[6] == "E"):
return 6
if (boardState[2] == boardState[6] == other_player):
if (boardState[4] == "E"):
return 4
if (boardState[6] == boardState[4] == other_player):
if (boardState[2] == "E"):
return 2
#check corners: 0, 2, 6, 8
for i in range(9):
if (boardState[i] == "E" and i % 2 == 0 and i != 4):
return i
#check center
if (boardState[4] == "E"):
return 4
#if all else fails, place it on the sides: 1, 3, 5, 7
for i in range(9):
if (boardState[i] == "E" and i % 2 == 1):
return i
def alek_computer_move(board_state, computer_symbol):
opponent_symbol = "O" if computer_symbol == "X" else "X"
# if there is a win available take it,
# if the opponent has a win available block it
for symbol in (computer_symbol, opponent_symbol):
for i in range(n**2):
if board_state[i] == "E":
tmp_board_state = board_state[:] # make a copy of board_state
tmp_board_state[i] = symbol
if board_value(tmp_board_state) == symbol:
return i
def random_computer_move(board_state):
print("USING RANDOM MOVE")
proposed_move = (n**2)//2 # center
while board_state[proposed_move] != "E":
proposed_move = np.random.randint(n**2)
return proposed_move
return random_computer_move(board_state)
# play games
# X vs O
total_rounds = 1000
alek_wins = 0
ziyong_wins = 0
for i in range(total_rounds):
if np.random.rand() < 0.5:
winner = play_game(alek_computer_move, ziyong_computer_move)
print(f"ALEK (X) VS ZIYONG (O), RESULT: {winner}\n\n\n")
if winner=="X":
alek_wins += 1
if winner == "O":
ziyong_wins+=1
else:
winner = play_game(ziyong_computer_move, alek_computer_move)
print(f"ALEK (X) VS ZIYONG (O), RESULT: {winner}\n\n\n")
if winner =="O":
alek_wins += 1
elif winner=="X":
ziyong_wins+=1
print(f"ALEK WON {alek_wins} / {total_rounds}")
print(f"ZIYONG WON {ziyong_wins} / {total_rounds}")