Update app.py
Browse files
app.py
CHANGED
@@ -1,11 +1,9 @@
|
|
1 |
import gradio as gr
|
2 |
from PIL import Image, ImageDraw
|
3 |
import random
|
|
|
4 |
|
5 |
def choose_move(board, player):
|
6 |
-
"""
|
7 |
-
Simple AI: chooses a random valid move from all legal flips.
|
8 |
-
"""
|
9 |
valid_moves = []
|
10 |
for r in range(8):
|
11 |
for c in range(8):
|
@@ -33,81 +31,65 @@ def get_flips(board, row, col, player):
|
|
33 |
r, c = row + dr, col + dc
|
34 |
buffer = []
|
35 |
while 0 <= r < 8 and 0 <= c < 8 and board[r][c] == -player:
|
36 |
-
buffer.append((r, c))
|
37 |
-
r += dr
|
38 |
-
c += dc
|
39 |
if buffer and 0 <= r < 8 and 0 <= c < 8 and board[r][c] == player:
|
40 |
flips.extend(buffer)
|
41 |
return flips
|
42 |
|
43 |
def apply_move(board, row, col, player):
|
44 |
flips = get_flips(board, row, col, player)
|
45 |
-
if not flips:
|
46 |
-
return False
|
47 |
board[row][col] = player
|
48 |
-
for r, c in flips:
|
49 |
-
board[r][c] = player
|
50 |
return True
|
51 |
|
52 |
def board_to_image(board, img_size=320):
|
53 |
-
|
54 |
img = Image.new('RGB', (img_size, img_size), 'green')
|
55 |
draw = ImageDraw.Draw(img)
|
56 |
for r in range(8):
|
57 |
for c in range(8):
|
58 |
-
x0, y0 = c *
|
59 |
-
x1,
|
60 |
-
draw.
|
61 |
-
|
62 |
-
draw.ellipse([x0+4, y0+4, x1-4, y1-4], fill='white')
|
63 |
-
elif board[r][c] == -1:
|
64 |
-
draw.ellipse([x0+4, y0+4, x1-4, y1-4], fill='black')
|
65 |
return img
|
66 |
|
67 |
def count_score(board):
|
68 |
-
|
69 |
-
|
70 |
-
return
|
71 |
|
72 |
-
def
|
73 |
board, player = state
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
if not (0
|
78 |
-
|
79 |
-
|
80 |
-
|
|
|
|
|
|
|
|
|
81 |
player = -player
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
def click_handler(evt: gr.SelectData, state):
|
94 |
-
# ユーザーの手
|
95 |
-
board_img, status_text, state = play_move(evt.index[0], evt.index[1], state)
|
96 |
-
board, player = state
|
97 |
-
# AI(White)が動く
|
98 |
-
if player == 1:
|
99 |
-
ai_move = choose_move(board, player)
|
100 |
-
if ai_move:
|
101 |
-
apply_move(board, ai_move[0], ai_move[1], player)
|
102 |
-
player = -player
|
103 |
-
black_score, white_score = count_score(board)
|
104 |
-
status_text = f"Black: {black_score} | White: {white_score} | {'Black' if player == -1 else 'White'} to move"
|
105 |
-
board_img = board_to_image(board)
|
106 |
-
state = (board, player)
|
107 |
-
return board_img, status_text, state
|
108 |
|
109 |
-
|
|
|
|
|
|
|
|
|
|
|
110 |
demo.launch()
|
111 |
-
|
112 |
-
if __name__ == "__main__":
|
113 |
-
main()
|
|
|
1 |
import gradio as gr
|
2 |
from PIL import Image, ImageDraw
|
3 |
import random
|
4 |
+
time
|
5 |
|
6 |
def choose_move(board, player):
|
|
|
|
|
|
|
7 |
valid_moves = []
|
8 |
for r in range(8):
|
9 |
for c in range(8):
|
|
|
31 |
r, c = row + dr, col + dc
|
32 |
buffer = []
|
33 |
while 0 <= r < 8 and 0 <= c < 8 and board[r][c] == -player:
|
34 |
+
buffer.append((r, c)); r += dr; c += dc
|
|
|
|
|
35 |
if buffer and 0 <= r < 8 and 0 <= c < 8 and board[r][c] == player:
|
36 |
flips.extend(buffer)
|
37 |
return flips
|
38 |
|
39 |
def apply_move(board, row, col, player):
|
40 |
flips = get_flips(board, row, col, player)
|
41 |
+
if not flips: return False
|
|
|
42 |
board[row][col] = player
|
43 |
+
for r, c in flips: board[r][c] = player
|
|
|
44 |
return True
|
45 |
|
46 |
def board_to_image(board, img_size=320):
|
47 |
+
cell = img_size // 8
|
48 |
img = Image.new('RGB', (img_size, img_size), 'green')
|
49 |
draw = ImageDraw.Draw(img)
|
50 |
for r in range(8):
|
51 |
for c in range(8):
|
52 |
+
x0, y0 = c*cell, r*cell; x1, y1 = x0+cell, y0+cell
|
53 |
+
draw.rectangle([x0,y0,x1,y1], outline='black')
|
54 |
+
if board[r][c]==1: draw.ellipse([x0+4,y0+4,x1-4,y1-4], fill='white')
|
55 |
+
elif board[r][c]==-1: draw.ellipse([x0+4,y0+4,x1-4,y1-4], fill='black')
|
|
|
|
|
|
|
56 |
return img
|
57 |
|
58 |
def count_score(board):
|
59 |
+
b = sum(cell==-1 for row in board for cell in row)
|
60 |
+
w = sum(cell==1 for row in board for cell in row)
|
61 |
+
return b, w
|
62 |
|
63 |
+
def click_handler(evt: gr.SelectData, state):
|
64 |
board, player = state
|
65 |
+
x, y = evt.index
|
66 |
+
cell = 320/8
|
67 |
+
r, c = int(y//cell), int(x//cell)
|
68 |
+
if not (0<=r<8 and 0<=c<8):
|
69 |
+
yield board_to_image(board), "ボード上をクリックしてください。", state
|
70 |
+
return
|
71 |
+
if not apply_move(board, r, c, player):
|
72 |
+
yield board_to_image(board), f"({r+1},{c+1})には置けません。", state
|
73 |
+
return
|
74 |
+
b,w = count_score(board)
|
75 |
+
commentary = f"あなたは({r+1},{c+1})に石を置きました。\n現在:黒{b} - 白{w}。AIの思考中…"
|
76 |
player = -player
|
77 |
+
yield board_to_image(board), commentary, (board, player)
|
78 |
+
time.sleep(2)
|
79 |
+
ai_mv = choose_move(board, player)
|
80 |
+
if ai_mv:
|
81 |
+
apply_move(board, ai_mv[0], ai_mv[1], player)
|
82 |
+
b,w = count_score(board)
|
83 |
+
commentary = f"AIは({ai_mv[0]+1},{ai_mv[1]+1})に石を置きました。\n現在:黒{b} - 白{w}。{'あなた' if player==-1 else 'AI'}の番です。"
|
84 |
+
else:
|
85 |
+
commentary = "AIはパスしました。あなたの番です。"
|
86 |
+
player = -player
|
87 |
+
yield board_to_image(board), commentary, (board, player)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
88 |
|
89 |
+
with gr.Blocks() as demo:
|
90 |
+
gr.HTML("<h2>オセロ(リバーシ)</h2>")
|
91 |
+
state = gr.State((initialize_board(), -1))
|
92 |
+
board_img = gr.Image(value=board_to_image(initialize_board()), interactive=True)
|
93 |
+
commentary = gr.Markdown("黒2 - 白2。黒の番です。")
|
94 |
+
board_img.select(click_handler, inputs=[state], outputs=[board_img, commentary, state])
|
95 |
demo.launch()
|
|
|
|
|
|