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

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +128 -162
app.py CHANGED
@@ -1,169 +1,135 @@
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()
 
 
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()