Muhammad10101's picture
Upload app.py
4222196 verified
import streamlit as st
import math
import random
class TicTacToe:
def __init__(self):
"""Initialize the game board"""
self.board = [[' ' for _ in range(3)] for _ in range(3)]
self.current_winner = None
def make_move(self, row, col, player):
"""Make a move on the board"""
if self.board[row][col] == ' ':
self.board[row][col] = player
return True
return False
def check_winner(self):
"""Check for a winner"""
# Check rows
for row in self.board:
if row[0] == row[1] == row[2] != ' ':
return row[0]
# Check columns
for col in range(3):
if self.board[0][col] == self.board[1][col] == self.board[2][col] != ' ':
return self.board[0][col]
# Check diagonals
if self.board[0][0] == self.board[1][1] == self.board[2][2] != ' ':
return self.board[0][0]
if self.board[0][2] == self.board[1][1] == self.board[2][0] != ' ':
return self.board[0][2]
return None
def is_board_full(self):
"""Check if the board is full"""
return all(cell != ' ' for row in self.board for cell in row)
def minimax(self, depth, is_maximizing, alpha, beta):
"""Minimax algorithm with Alpha-Beta pruning"""
winner = self.check_winner()
# Terminal states
if winner == 'X':
return 1
elif winner == 'O':
return -1
elif self.is_board_full():
return 0
if is_maximizing:
max_eval = -math.inf
for i in range(3):
for j in range(3):
if self.board[i][j] == ' ':
self.board[i][j] = 'X'
eval = self.minimax(depth + 1, False, alpha, beta)
self.board[i][j] = ' '
max_eval = max(max_eval, eval)
alpha = max(alpha, eval)
if beta <= alpha:
break
return max_eval
else:
min_eval = math.inf
for i in range(3):
for j in range(3):
if self.board[i][j] == ' ':
self.board[i][j] = 'O'
eval = self.minimax(depth + 1, True, alpha, beta)
self.board[i][j] = ' '
min_eval = min(min_eval, eval)
beta = min(beta, eval)
if beta <= alpha:
break
return min_eval
def find_best_move(self):
"""Find the best move for the AI"""
best_val = -math.inf
best_move = None
for i in range(3):
for j in range(3):
if self.board[i][j] == ' ':
self.board[i][j] = 'X'
move_val = self.minimax(0, False, -math.inf, math.inf)
self.board[i][j] = ' '
if move_val > best_val:
best_move = (i, j)
best_val = move_val
return best_move
def main():
# Set page configuration
st.set_page_config(
page_title="Tic-Tac-Toe AI",
page_icon=":game_die:",
layout="centered"
)
# Custom CSS for styling
st.markdown("""
<style>
.stButton>button {
width: 100px;
height: 100px;
font-size: 48px;
margin: 5px;
}
.title {
text-align: center;
color: #4a4a4a;
}
.subtitle {
text-align: center;
color: #6a6a6a;
}
</style>
""", unsafe_allow_html=True)
# Title and introduction
st.markdown("<h1 class='title'>🎲 Tic-Tac-Toe AI πŸ€–</h1>", unsafe_allow_html=True)
st.markdown("<h3 class='subtitle'>Can you beat the AI?</h3>", unsafe_allow_html=True)
# Initialize game state
if 'game' not in st.session_state:
st.session_state.game = TicTacToe()
st.session_state.game_over = False
st.session_state.winner = None
# Function to handle button clicks
def button_click(row, col):
# Check if game is not over and the cell is empty
if not st.session_state.game_over and st.session_state.game.board[row][col] == ' ':
# Player's move
st.session_state.game.make_move(row, col, 'O')
# Check for player win
winner = st.session_state.game.check_winner()
if winner:
st.session_state.game_over = True
st.session_state.winner = winner
return
# Check for draw
if st.session_state.game.is_board_full():
st.session_state.game_over = True
return
# AI's move
ai_move = st.session_state.game.find_best_move()
if ai_move:
st.session_state.game.make_move(ai_move[0], ai_move[1], 'X')
# Check for AI win
winner = st.session_state.game.check_winner()
if winner:
st.session_state.game_over = True
st.session_state.winner = winner
# Render the game board
game_board = st.columns(3)
for row in range(3):
with game_board[row % 3]:
for col in range(3):
# Create a button for each cell
button_label = st.session_state.game.board[row][col]
button_key = f"button_{row}_{col}"
# Style buttons based on their content
if button_label == 'O':
button_style = "background-color: #FF6B6B; color: white;"
elif button_label == 'X':
button_style = "background-color: #4ECDC4; color: white;"
else:
button_style = ""
# Create the button
if st.button(button_label, key=button_key,
on_click=button_click,
args=(row, col),
disabled=st.session_state.game_over or button_label != ' ',
help="Click to make your move"):
pass
# Display game result
if st.session_state.game_over:
if st.session_state.winner == 'O':
st.success("πŸŽ‰ Congratulations! You won!")
elif st.session_state.winner == 'X':
st.error("πŸ€– AI wins! Better luck next time.")
else:
st.warning("🀝 It's a draw!")
# Restart game button
if st.button("New Game", help="Start a new game"):
st.session_state.game = TicTacToe()
st.session_state.game_over = False
st.session_state.winner = None
st.rerun()
if __name__ == "__main__":
main()