Update app.py
Browse files
app.py
CHANGED
@@ -1,95 +1,95 @@
|
|
1 |
import gradio as gr
|
2 |
-
from PIL import Image, ImageDraw
|
3 |
import random
|
4 |
import time
|
5 |
|
6 |
def choose_move(board, player):
|
7 |
-
|
8 |
-
|
9 |
-
for c in range(8):
|
10 |
-
if get_flips(board, r, c, player):
|
11 |
-
valid_moves.append((r, c))
|
12 |
-
if not valid_moves:
|
13 |
-
return None
|
14 |
-
return random.choice(valid_moves)
|
15 |
|
16 |
def initialize_board():
|
17 |
-
board = [[0
|
18 |
board[3][3], board[4][4] = 1, 1
|
19 |
board[3][4], board[4][3] = -1, -1
|
20 |
return board
|
21 |
|
22 |
-
DIRECTIONS = [(-1,
|
23 |
-
(0, -1), (0, 1),
|
24 |
-
(1, -1), (1, 0), (1, 1)]
|
25 |
|
26 |
-
def get_flips(board,
|
27 |
-
if board[
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
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,
|
40 |
-
|
41 |
-
if not
|
42 |
-
board[
|
43 |
-
for
|
44 |
return True
|
45 |
|
46 |
-
def
|
47 |
-
cell
|
48 |
-
|
49 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
50 |
for r in range(8):
|
51 |
for c in range(8):
|
52 |
-
x0,
|
53 |
-
|
54 |
-
|
55 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
56 |
return img
|
57 |
|
58 |
-
def
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
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
|
72 |
-
|
|
|
|
|
73 |
return
|
74 |
-
|
75 |
-
|
76 |
-
player = -player
|
77 |
-
yield board_to_image(board), commentary, (board, player)
|
78 |
time.sleep(2)
|
79 |
-
ai_mv
|
80 |
if ai_mv:
|
81 |
-
apply_move(board,
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
commentary = "AIはパスしました。あなたの番です。"
|
86 |
-
player = -player
|
87 |
-
yield board_to_image(board), commentary, (board, player)
|
88 |
|
89 |
with gr.Blocks() as demo:
|
90 |
-
gr.
|
91 |
-
|
92 |
-
|
93 |
-
commentary = gr.Markdown("黒2 - 白2。黒の番です。")
|
94 |
-
board_img.select(click_handler, inputs=[state], outputs=[board_img, commentary, state])
|
95 |
demo.launch()
|
|
|
1 |
import gradio as gr
|
2 |
+
from PIL import Image, ImageDraw, ImageFont
|
3 |
import random
|
4 |
import time
|
5 |
|
6 |
def choose_move(board, player):
|
7 |
+
moves = [(r,c) for r in range(8) for c in range(8) if get_flips(board, r, c, player)]
|
8 |
+
return random.choice(moves) if moves else None
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
|
10 |
def initialize_board():
|
11 |
+
board = [[0]*8 for _ in range(8)]
|
12 |
board[3][3], board[4][4] = 1, 1
|
13 |
board[3][4], board[4][3] = -1, -1
|
14 |
return board
|
15 |
|
16 |
+
DIRECTIONS = [(-1,-1),(-1,0),(-1,1),(0,-1),(0,1),(1,-1),(1,0),(1,1)]
|
|
|
|
|
17 |
|
18 |
+
def get_flips(board, r, c, p):
|
19 |
+
if board[r][c]!=0: return []
|
20 |
+
flips=[]
|
21 |
+
for dr,dc in DIRECTIONS:
|
22 |
+
rr,cc=r+dr,c+dc; buf=[]
|
23 |
+
while 0<=rr<8 and 0<=cc<8 and board[rr][cc]==-p:
|
24 |
+
buf.append((rr,cc)); rr+=dr; cc+=dc
|
25 |
+
if buf and 0<=rr<8 and 0<=cc<8 and board[rr][cc]==p:
|
26 |
+
flips+=buf
|
|
|
|
|
27 |
return flips
|
28 |
|
29 |
+
def apply_move(board,r,c,p):
|
30 |
+
f=get_flips(board,r,c,p)
|
31 |
+
if not f: return False
|
32 |
+
board[r][c]=p
|
33 |
+
for rr,cc in f: board[rr][cc]=p
|
34 |
return True
|
35 |
|
36 |
+
def count_score(board):
|
37 |
+
b=sum(cell==-1 for row in board for cell in row)
|
38 |
+
w=sum(cell==1 for row in board for cell in row)
|
39 |
+
return b,w
|
40 |
+
|
41 |
+
def board_to_image(board, last_user, last_ai, player):
|
42 |
+
size=360; cell=size//8
|
43 |
+
img=Image.new('RGB',(size,size+cell),'darkgreen'); d=ImageDraw.Draw(img)
|
44 |
+
# スコアボード
|
45 |
+
b,w=count_score(board)
|
46 |
+
d.rectangle([0,0,size,cell],fill='navy')
|
47 |
+
fnt=ImageFont.load_default()
|
48 |
+
d.text((10,2),f"黒: {b}",font=fnt,fill='yellow')
|
49 |
+
d.text((size-60,2),f"白: {w}",font=fnt,fill='yellow')
|
50 |
+
# 盤面
|
51 |
for r in range(8):
|
52 |
for c in range(8):
|
53 |
+
x0,y0=c*cell,cell+r*cell; x1,y1=x0+cell,y0+cell
|
54 |
+
d.rectangle([x0,y0,x1,y1],outline='black')
|
55 |
+
# 候補手
|
56 |
+
if board[r][c]==0 and get_flips(board,r,c,player):
|
57 |
+
d.ellipse([x0+cell*0.4,y0+cell*0.4,x0+cell*0.6,y0+cell*0.6],fill='yellow')
|
58 |
+
if board[r][c]==1: d.ellipse([x0+4,y0+4,x1-4,y1-4],fill='white')
|
59 |
+
if board[r][c]==-1: d.ellipse([x0+4,y0+4,x1-4,y1-4],fill='black')
|
60 |
+
# 着手マーク
|
61 |
+
if last_user:
|
62 |
+
r,c=last_user; x0,y0=c*cell,cell+r*cell; x1,y1=x0+cell,y1=y0+cell
|
63 |
+
d.rectangle([x0,y0,x1,y1],outline='red',width=3)
|
64 |
+
if last_ai:
|
65 |
+
r,c=last_ai; x0,y0=c*cell,cell+r*cell; x1,y1=x0+cell,y0+cell
|
66 |
+
d.rectangle([x0,y0,x1,y1],outline='blue',width=3)
|
67 |
return img
|
68 |
|
69 |
+
def click_handler(evt:gr.SelectData,state):
|
70 |
+
board,player,last_user,last_ai=state
|
71 |
+
x,y=evt.index; cell=360//8
|
72 |
+
c,r=int(x//cell),int((y-cell)//cell)
|
73 |
+
if r<0 or r>7 or c<0 or c>7:
|
74 |
+
yield board_to_image(board,last_user,last_ai,player),state
|
|
|
|
|
|
|
|
|
|
|
|
|
75 |
return
|
76 |
+
if apply_move(board,r,c,player):
|
77 |
+
last_user=(r,c)
|
78 |
+
else:
|
79 |
+
yield board_to_image(board,last_user,last_ai,player),(board,player,last_user,last_ai)
|
80 |
return
|
81 |
+
player=-player
|
82 |
+
yield board_to_image(board,last_user,last_ai,player),(board,player,last_user,last_ai)
|
|
|
|
|
83 |
time.sleep(2)
|
84 |
+
ai_mv=choose_move(board,player)
|
85 |
if ai_mv:
|
86 |
+
apply_move(board,ai_mv[0],ai_mv[1],player)
|
87 |
+
last_ai=(ai_mv[0],ai_mv[1])
|
88 |
+
player=-player
|
89 |
+
yield board_to_image(board,last_user,last_ai,player),(board,player,last_user,last_ai)
|
|
|
|
|
|
|
90 |
|
91 |
with gr.Blocks() as demo:
|
92 |
+
state=gr.State((initialize_board(),-1,None,None))
|
93 |
+
img=gr.Image(value=board_to_image(initialize_board(),None,None,-1),interactive=True)
|
94 |
+
img.select(click_handler,inputs=[state],outputs=[img,state])
|
|
|
|
|
95 |
demo.launch()
|