Spaces:
Build error
Build error
File size: 8,319 Bytes
84e2f44 c3874a1 c325f0a c3874a1 c325f0a 3b6c3b6 c325f0a c3874a1 c325f0a c3874a1 c325f0a c3874a1 c325f0a c3874a1 3b6c3b6 c325f0a c3874a1 c325f0a 3b6c3b6 c325f0a 3b6c3b6 c325f0a 84e2f44 3b6c3b6 84e2f44 06d5f8a 3b6c3b6 5c34f36 06d5f8a 5c34f36 06d5f8a 3b6c3b6 06d5f8a 3b6c3b6 c325f0a 282332e 06d5f8a c325f0a bdb0baf 3b6c3b6 bdb0baf 06d5f8a 3b6c3b6 06d5f8a 3b6c3b6 06d5f8a 3b6c3b6 06d5f8a 84e2f44 cd10e4c 3b6c3b6 cd10e4c bdb0baf cd10e4c bdb0baf cd10e4c 3b6c3b6 cd10e4c 3b6c3b6 cd10e4c 3b6c3b6 c325f0a cd10e4c 3b6c3b6 5c34f36 cd10e4c e15098b cd10e4c 3b6c3b6 cd10e4c 3b6c3b6 06d5f8a 84e2f44 06d5f8a c3874a1 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 |
import random
import numpy as np
import gradio as gr
class TicTacToe:
def __init__(self):
self.board = [' '] * 9
self.current_player = 'X'
def display_board(self):
print("\n")
for i in range(3):
print(" | ".join(self.board[i * 3:(i + 1) * 3]))
if i < 2:
print("---------")
print("\n")
def make_move(self, position):
self.board[position] = self.current_player
def switch_player(self):
self.current_player = 'O' if self.current_player == 'X' else 'X'
def check_winner(self):
winning_combinations = [
[0, 1, 2], [3, 4, 5], [6, 7, 8], # Rows
[0, 3, 6], [1, 4, 7], [2, 5, 8], # Columns
[0, 4, 8], [2, 4, 6] # Diagonals
]
for combo in winning_combinations:
if self.board[combo[0]] == self.board[combo[1]] == self.board[combo[2]] != ' ':
return self.board[combo[0]]
return None
def is_draw(self):
return ' ' not in self.board
def reset_board(self):
self.board = [' '] * 9
self.current_player = 'X'
class MinimaxPlayer:
def __init__(self, symbol):
self.symbol = symbol
def minimax(self, game, is_maximizing):
winner = game.check_winner()
if winner == self.symbol:
return 1
elif winner == ('O' if self.symbol == 'X' else 'X'):
return -1
elif game.is_draw():
return 0
if is_maximizing:
best_score = -float('inf')
for i in range(9):
if game.board[i] == ' ':
game.board[i] = self.symbol
score = self.minimax(game, False)
game.board[i] = ' '
best_score = max(score, best_score)
return best_score
else:
best_score = float('inf')
for i in range(9):
if game.board[i] == ' ':
game.board[i] = ('O' if self.symbol == 'X' else 'X')
score = self.minimax(game, True)
game.board[i] = ' '
best_score = min(score, best_score)
return best_score
def get_move(self, game):
best_score = -float('inf')
best_move = None
for i in range(9):
if game.board[i] == ' ':
game.board[i] = self.symbol
score = self.minimax(game, False)
game.board[i] = ' '
if score > best_score:
best_score = score
best_move = i
return best_move
class QLearningPlayer:
def __init__(self, symbol, learning_rate=0.1, discount_factor=0.9, exploration_rate=1.0):
self.symbol = symbol
self.q_table = {}
self.learning_rate = learning_rate
self.discount_factor = discount_factor
self.exploration_rate = exploration_rate
def get_state(self, game):
return ''.join(game.board)
def choose_action(self, game):
state = self.get_state(game)
if random.random() < self.exploration_rate:
return random.choice([i for i in range(9) if game.board[i] == ' '])
if state not in self.q_table:
self.q_table[state] = np.zeros(9)
return np.argmax(self.q_table[state])
def update_q_table(self, state, action, reward, next_state):
if state not in self.q_table:
self.q_table[state] = np.zeros(9)
if next_state not in self.q_table:
self.q_table[next_state] = np.zeros(9)
self.q_table[state][action] += self.learning_rate * (
reward + self.discount_factor * np.max(self.q_table[next_state]) - self.q_table[state][action]
)
def train(self, episodes):
for _ in range(episodes):
game = TicTacToe()
state = self.get_state(game)
while True:
action = self.choose_action(game)
game.make_move(action)
next_state = self.get_state(game)
winner = game.check_winner()
if winner == self.symbol:
reward = 1
self.update_q_table(state, action, reward, next_state)
break
elif winner:
reward = -1
self.update_q_table(state, action, reward, next_state)
break
elif game.is_draw():
reward = 0.5
self.update_q_table(state, action, reward, next_state)
break
else:
reward = 0
self.update_q_table(state, action, reward, next_state)
game.switch_player()
state = next_state
# Global game instance
game = TicTacToe()
game_mode = "human_vs_human"
minimax_player = MinimaxPlayer('O')
qlearning_player = QLearningPlayer('O')
qlearning_player.train(1000) # Pre-train the Q-learning agent
def render_board():
"""Convert the game board to a grid of buttons"""
board = []
for i in range(3):
row = []
for j in range(3):
idx = i * 3 + j
value = game.board[idx] if game.board[idx] != ' ' else ""
row.append(value)
board.append(row)
return board
def check_game_end():
"""Check if the game has ended"""
return game.check_winner() or game.is_draw()
def get_game_status():
"""Get the current game status message"""
winner = game.check_winner()
if winner:
return f"Player {winner} wins!"
elif game.is_draw():
return "It's a draw!"
else:
return f"Current player: {game.current_player}"
def reset_game(game_mode, difficulty):
"""Reset the game board"""
game.reset_board()
return render_board(), "Game reset! Current player: X"
def make_move(evt: gr.SelectData, game_mode, difficulty):
"""Handle player moves and AI responses"""
row, col = evt.index
position = row * 3 + col
# Human move
if game.board[position] == ' ':
game.make_move(position)
if check_game_end():
return render_board(), get_game_status()
# If in human_vs_human mode, switch player manually
if game_mode == "human_vs_human":
game.switch_player()
# AI move (if playing against AI)
elif game_mode != "human_vs_human":
# Switch player before AI move
game.switch_player()
# Minimax or Q-Learning AI move
if game_mode == "minimax":
ai_move = minimax_player.get_move(game)
else: # q_learning
ai_move = qlearning_player.choose_action(game)
game.make_move(ai_move)
if check_game_end():
return render_board(), get_game_status()
# Switch player after AI move
game.switch_player()
return render_board(), get_game_status()
def create_gui():
"""Create the Gradio interface"""
with gr.Blocks() as interface:
gr.Markdown("# Tic Tac Toe with AI")
with gr.Row():
game_mode = gr.Radio(
["Human_vs_Human", "AI", "Q_learning"],
label="Game Mode",
value="human_vs_human"
)
difficulty = gr.Radio(
["Easy", "Medium", "Hard"],
label="AI Difficulty",
value="medium"
)
board = gr.DataFrame(
render_board(),
headers=[""] * 3, # Empty headers for 3 columns
interactive=True,
col_count=(3, "fixed"),
row_count=(3, "fixed")
)
status = gr.Textbox(value="Current player: X", label="Status")
reset_btn = gr.Button("Reset Game")
# Event handlers
board.select(
make_move,
[game_mode, difficulty],
[board, status]
)
reset_btn.click(
reset_game,
[game_mode, difficulty],
[board, status]
)
return interface
# Launch the interface
if __name__ == "__main__":
interface = create_gui()
interface.launch()
|