Hi everybody. The problem I have is building a tic tac toe game with AI. But when running on the web, you have to press twice for the x to appear. Even if you press the first time, x won't appear yet then o will appear. Hope everyone can help me.

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(“:arrows_counterclockwise: 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()

Please edit your topic to wrap your code in a code block using triple backticks (```) at the beginning and at the end of your code. It will make easier for us to read your code.