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.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.