OrifjonKenjayev commited on
Commit
2e19252
·
verified ·
1 Parent(s): 2820e47

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +162 -128
app.py CHANGED
@@ -1,135 +1,169 @@
1
  import gradio as gr
 
 
2
 
3
- # Tic Tac Toe logic with Minimax AI
4
  class TicTacToe:
5
  def __init__(self):
6
- self.board = [" "] * 9
7
- self.current_winner = None
8
-
9
- def print_board(self):
10
- for row in [self.board[i * 3:(i + 1) * 3] for i in range(3)]:
11
- print("| " + " | ".join(row) + " |")
12
-
13
- def available_moves(self):
14
- return [i for i, spot in enumerate(self.board) if spot == " "]
15
-
16
- def empty_squares(self):
17
- return " " in self.board
18
-
19
- def num_empty_squares(self):
20
- return len(self.available_moves())
21
-
22
- def make_move(self, square, letter):
23
- if self.board[square] == " ":
24
- self.board[square] = letter
25
- if self.winner(square, letter):
26
- self.current_winner = letter
27
- return True
28
- return False
29
-
30
- def winner(self, square, letter):
31
- # Check row
32
- row_ind = square // 3
33
- row = self.board[row_ind * 3:(row_ind + 1) * 3]
34
- if all([spot == letter for spot in row]):
35
- return True
36
- # Check column
37
- col_ind = square % 3
38
- column = [self.board[col_ind + i * 3] for i in range(3)]
39
- if all([spot == letter for spot in column]):
40
- return True
41
- # Check diagonals
42
- if square % 2 == 0:
43
- diagonal1 = [self.board[i] for i in [0, 4, 8]]
44
- if all([spot == letter for spot in diagonal1]):
45
- return True
46
- diagonal2 = [self.board[i] for i in [2, 4, 6]]
47
- if all([spot == letter for spot in diagonal2]):
48
- return True
49
- return False
50
-
51
- def minimax(self, state, player):
52
- max_player = "O"
53
- other_player = "X" if player == "O" else "O"
54
-
55
- if self.current_winner == other_player:
56
- return {"position": None, "score": 1 * (state.count(" ") + 1) if other_player == max_player else -1 * (
57
- state.count(" ") + 1)}
58
- elif not self.empty_squares():
59
- return {"position": None, "score": 0}
60
-
61
- if player == max_player:
62
- best = {"position": None, "score": -float("inf")}
63
  else:
64
- best = {"position": None, "score": float("inf")}
65
-
66
- for possible_move in self.available_moves():
67
- self.board[possible_move] = player
68
- sim_score = self.minimax(self.board, other_player)
69
-
70
- self.board[possible_move] = " "
71
- sim_score["position"] = possible_move
72
-
73
- if player == max_player:
74
- if sim_score["score"] > best["score"]:
75
- best = sim_score
76
- else:
77
- if sim_score["score"] < best["score"]:
78
- best = sim_score
79
-
80
- return best
81
-
82
- def ai_move(self):
83
- if len(self.available_moves()) == 9:
84
- square = 4
85
- else:
86
- square = self.minimax(self.board, "O")["position"]
87
- self.make_move(square, "O")
88
- return square
89
-
90
-
91
- # Gradio Interface
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
  game = TicTacToe()
93
 
94
- def play_tic_tac_toe(human_move):
95
- if not game.empty_squares() or game.current_winner is not None:
96
- return {"output": "Game Over! Reset to play again.", "board": game.board}
97
-
98
- if game.board[human_move] != " ":
99
- return {"output": "Invalid move. Try again.", "board": game.board}
100
-
101
- game.make_move(human_move, "X")
102
- if game.current_winner:
103
- return {"output": "You win!", "board": game.board}
104
-
105
- if game.empty_squares():
106
- ai_move = game.ai_move()
107
- if game.current_winner:
108
- return {"output": "AI wins!", "board": game.board}
109
-
110
- return {"output": "Your move.", "board": game.board}
111
-
112
- def reset_game():
113
- global game
114
- game = TicTacToe()
115
- return {"output": "Game reset! Your move.", "board": game.board}
116
-
117
- # Gradio app
118
- def render_game(human_move=None):
119
- if human_move is None:
120
- return reset_game()
121
- return play_tic_tac_toe(int(human_move))
122
-
123
- interface = gr.Interface(
124
- fn=render_game,
125
- inputs=gr.Dropdown(choices=[str(i) for i in range(9)], label="Your Move (0-8)"),
126
- outputs=[
127
- gr.Textbox(label="Game Status"),
128
- gr.Textbox(label="Current Board State")
129
- ],
130
- live=True,
131
- title="Tic Tac Toe with AI",
132
- description="Play Tic Tac Toe against an AI powered by the Minimax algorithm!"
133
- )
134
-
135
- interface.launch()
 
1
  import gradio as gr
2
+ import numpy as np
3
+ from typing import List, Tuple, Optional
4
 
 
5
  class TicTacToe:
6
  def __init__(self):
7
+ self.board = np.zeros((3, 3))
8
+ self.human_player = 1
9
+ self.ai_player = -1
10
+
11
+ def reset_board(self):
12
+ self.board = np.zeros((3, 3))
13
+ return self.format_board()
14
+
15
+ def check_winner(self) -> Optional[int]:
16
+ # Check rows, columns and diagonals
17
+ for player in [self.human_player, self.ai_player]:
18
+ # Rows and columns
19
+ for i in range(3):
20
+ if all(self.board[i, :] == player) or all(self.board[:, i] == player):
21
+ return player
22
+ # Diagonals
23
+ if all(np.diag(self.board) == player) or all(np.diag(np.fliplr(self.board)) == player):
24
+ return player
25
+
26
+ # Check for draw
27
+ if np.all(self.board != 0):
28
+ return 0
29
+
30
+ return None
31
+
32
+ def get_valid_moves(self) -> List[Tuple[int, int]]:
33
+ return [(i, j) for i in range(3) for j in range(3) if self.board[i, j] == 0]
34
+
35
+ def minimax(self, depth: int, is_maximizing: bool, alpha: float = float('-inf'), beta: float = float('inf')) -> Tuple[int, Optional[Tuple[int, int]]]:
36
+ winner = self.check_winner()
37
+ if winner is not None:
38
+ return winner * 100, None
39
+
40
+ if is_maximizing:
41
+ best_score = float('-inf')
42
+ best_move = None
43
+ for move in self.get_valid_moves():
44
+ self.board[move] = self.ai_player
45
+ score, _ = self.minimax(depth + 1, False, alpha, beta)
46
+ self.board[move] = 0
47
+
48
+ if score > best_score:
49
+ best_score = score
50
+ best_move = move
51
+
52
+ alpha = max(alpha, best_score)
53
+ if beta <= alpha:
54
+ break
55
+
56
+ return best_score, best_move
 
 
 
 
 
 
 
57
  else:
58
+ best_score = float('inf')
59
+ best_move = None
60
+ for move in self.get_valid_moves():
61
+ self.board[move] = self.human_player
62
+ score, _ = self.minimax(depth + 1, True, alpha, beta)
63
+ self.board[move] = 0
64
+
65
+ if score < best_score:
66
+ best_score = score
67
+ best_move = move
68
+
69
+ beta = min(beta, best_score)
70
+ if beta <= alpha:
71
+ break
72
+
73
+ return best_score, best_move
74
+
75
+ def ai_move(self) -> str:
76
+ if len(self.get_valid_moves()) == 0:
77
+ return self.format_board()
78
+
79
+ _, best_move = self.minimax(0, True)
80
+ if best_move is not None:
81
+ self.board[best_move] = self.ai_player
82
+
83
+ return self.format_board()
84
+
85
+ def format_board(self) -> str:
86
+ symbols = {0: " ", 1: "X", -1: "O"}
87
+ return "\n".join([
88
+ "-------------",
89
+ f"| {symbols[self.board[0,0]]} | {symbols[self.board[0,1]]} | {symbols[self.board[0,2]]} |",
90
+ "-------------",
91
+ f"| {symbols[self.board[1,0]]} | {symbols[self.board[1,1]]} | {symbols[self.board[1,2]]} |",
92
+ "-------------",
93
+ f"| {symbols[self.board[2,0]]} | {symbols[self.board[2,1]]} | {symbols[self.board[2,2]]} |",
94
+ "-------------"
95
+ ])
96
+
97
+ def make_move(self, row: int, col: int) -> Tuple[str, str]:
98
+ # Check if move is valid
99
+ if self.board[row, col] != 0:
100
+ return self.format_board(), "Invalid move! Cell already taken."
101
+
102
+ # Make human move
103
+ self.board[row, col] = self.human_player
104
+
105
+ # Check if game is over after human move
106
+ winner = self.check_winner()
107
+ if winner is not None:
108
+ if winner == self.human_player:
109
+ return self.format_board(), "You win!"
110
+ elif winner == 0:
111
+ return self.format_board(), "It's a draw!"
112
+
113
+ # Make AI move
114
+ self.ai_move()
115
+
116
+ # Check if game is over after AI move
117
+ winner = self.check_winner()
118
+ if winner is not None:
119
+ if winner == self.ai_player:
120
+ return self.format_board(), "AI wins!"
121
+ elif winner == 0:
122
+ return self.format_board(), "It's a draw!"
123
+
124
+ return self.format_board(), "Game in progress"
125
+
126
+ # Create game instance
127
  game = TicTacToe()
128
 
129
+ def play_game(row: int, col: int, board_state: str, game_status: str) -> Tuple[str, str]:
130
+ if "win" in game_status or "draw" in game_status:
131
+ return board_state, game_status
132
+ return game.make_move(row, col)
133
+
134
+ def reset_game() -> Tuple[str, str]:
135
+ return game.reset_board(), "Game reset! Your turn (X)"
136
+
137
+ # Create Gradio interface
138
+ with gr.Blocks() as demo:
139
+ gr.Markdown("# Tic Tac Toe vs AI")
140
+ gr.Markdown("You play as X, AI plays as O. Click the buttons to make your move!")
141
+
142
+ with gr.Row():
143
+ # Game board display
144
+ board_display = gr.Textbox(value=game.format_board(), label="Game Board", lines=7)
145
+ game_status = gr.Textbox(value="Your turn (X)", label="Game Status")
146
+
147
+ # Create 3x3 grid of buttons
148
+ with gr.Row():
149
+ for i in range(3):
150
+ with gr.Column():
151
+ for j in range(3):
152
+ btn = gr.Button(f"Row {i}, Col {j}")
153
+ btn.click(
154
+ fn=play_game,
155
+ inputs=[
156
+ gr.Number(value=i, visible=False),
157
+ gr.Number(value=j, visible=False),
158
+ board_display,
159
+ game_status
160
+ ],
161
+ outputs=[board_display, game_status]
162
+ )
163
+
164
+ # Reset button
165
+ reset_btn = gr.Button("Reset Game")
166
+ reset_btn.click(fn=reset_game, inputs=[], outputs=[board_display, game_status])
167
+
168
+ # Launch app
169
+ demo.launch()