import streamlit as st
from random import choice
from math import inf as infinity
Constants for players
HUMAN = -1
COMP = +1
Initialize session_state if not already set
if “board” not in st.session_state:
st.session_state.board = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
if “current_player” not in st.session_state:
st.session_state.current_player = HUMAN
if “h_choice” not in st.session_state:
st.session_state.h_choice = “X”
if “c_choice” not in st.session_state:
st.session_state.c_choice = “O”
if “game_over” not in st.session_state:
st.session_state.game_over = False
Function to check for a win
def wins(state, player):
win_state = [
[state[0][0], state[0][1], state[0][2]],
[state[1][0], state[1][1], state[1][2]],
[state[2][0], state[2][1], state[2][2]],
[state[0][0], state[1][0], state[2][0]],
[state[0][1], state[1][1], state[2][1]],
[state[0][2], state[1][2], state[2][2]],
[state[0][0], state[1][1], state[2][2]],
[state[2][0], state[1][1], state[0][2]],
]
return [player, player, player] in win_state
Evaluate the board
def evaluate(state):
if wins(state, COMP):
return +1
elif wins(state, HUMAN):
return -1
else:
return 0
Check if the game is over
def check_game_over():
if wins(st.session_state.board, HUMAN):
st.session_state.game_over = True
st.success(“Bạn đã thắng!”)
elif wins(st.session_state.board, COMP):
st.session_state.game_over = True
st.error(“Máy tính đã thắng!”)
elif all(cell != 0 for row in st.session_state.board for cell in row):
st.session_state.game_over = True
st.info(“Trận đấu hòa!”)
Get all empty cells
def empty_cells(state):
return [[x, y] for x, row in enumerate(state) for y, cell in enumerate(row) if cell == 0]
Set a move on the board
def set_move(x, y, player):
if [x, y] in empty_cells(st.session_state.board):
st.session_state.board[y] = player
return True
return False
AI’s turn
def ai_turn():
depth = len(empty_cells(st.session_state.board))
if depth == 0 or st.session_state.game_over:
return
if depth == 9:
x, y = choice(empty_cells(st.session_state.board))
else:
move = minimax(st.session_state.board, depth, COMP)
x, y = move[0], move[1]
set_move(x, y, COMP)
check_game_over()
Minimax algorithm for AI
def minimax(state, depth, player):
if player == COMP:
best = [-1, -1, -infinity]
else:
best = [-1, -1, +infinity]
if depth == 0 or wins(state, HUMAN) or wins(state, COMP):
score = evaluate(state)
return [-1, -1, score]
for cell in empty_cells(state):
x, y = cell
state[x][y] = player
score = minimax(state, depth - 1, -player)
state[x][y] = 0
score[0], score[1] = x, y
if player == COMP:
if score[2] > best[2]:
best = score
else:
if score[2] < best[2]:
best = score
return best
def human_turn(x, y):
if set_move(x, y, HUMAN):
check_game_over() # Check game over status immediately after the move
if not st.session_state.game_over:
ai_turn() # Let AI make its move if the game isn’t over
Streamlit UI
st.title(“Tic Tac Toe with Streamlit”)
st.write(“Hãy cố gắng chiến thắng nhé!”)
Display the board as a grid
st.write(“### Bàn cờ:”)
for i, row in enumerate(st.session_state.board):
cols = st.columns(3, gap=“small”) # Create 3 columns for each row
for j, cell in enumerate(row):
with cols[j]:
if cell == HUMAN:
st.button(st.session_state.h_choice, disabled=True, key=“{}-{}”.format(i, j))
elif cell == COMP:
st.button(st.session_state.c_choice, disabled=True, key=“{}-{}”.format(i, j))
else:
if st.button(" “, key=”{}-{}".format(i, j)) and not st.session_state.game_over:
human_turn(i, j)
Reset button
if st.button(“ Chơi lại”):
st.session_state.board = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
st.session_state.current_player = HUMAN
st.session_state.game_over = False
st.experimental_rerun()