Renecto commited on
Commit
c0fee0a
·
verified ·
1 Parent(s): cc9d79f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +80 -75
app.py CHANGED
@@ -1,11 +1,9 @@
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
- valid = [(r, c) for r in range(8) for c in range(8) if get_flips(board, r, c, player)]
8
- return random.choice(valid) if valid else None
9
 
10
  def initialize_board():
11
  b = [[0]*8 for _ in range(8)]
@@ -13,94 +11,101 @@ def initialize_board():
13
  b[3][4], b[4][3] = -1, -1
14
  return b
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')
44
- draw = ImageDraw.Draw(img)
45
- # Scoreboard
46
- b, w = count_score(board)
47
- draw.rectangle([0,0,size,cell], fill='navy')
48
- font = ImageFont.load_default()
49
- draw.text((10,2), f" 黒: {b}", font=font, fill='yellow')
50
- draw.text((size-80,2), f"白: {w}", font=font, fill='yellow')
 
 
 
 
 
51
  # Board
52
  for r in range(8):
53
  for c in range(8):
54
- x0, y0 = c*cell, cell + r*cell
55
- x1, y1 = x0+cell, y0+cell
56
- draw.rectangle([x0,y0,x1,y1], outline='black')
57
- # possible moves
58
- if board[r][c]==0 and get_flips(board, r, c, player):
59
- draw.ellipse([x0+cell*0.4, y0+cell*0.4, x0+cell*0.6, y0+cell*0.6], fill='yellow')
60
- if board[r][c]==1:
61
- draw.ellipse([x0+4, y0+4, x1-4, y1-4], fill='white')
62
- if board[r][c]==-1:
63
- draw.ellipse([x0+4, y0+4, x1-4, y1-4], fill='black')
64
  # markers
65
- if last_user:
66
- ur, uc = last_user
67
- x0, y0 = uc*cell, cell + ur*cell; x1, y1 = x0+cell, y0+cell
68
- draw.rectangle([x0,y0,x1,y1], outline='red', width=4)
69
- if last_ai:
70
- ar, ac = last_ai
71
- x0, y0 = ac*cell, cell + ar*cell; x1, y1 = x0+cell, y0+cell
72
- draw.rectangle([x0,y0,x1,y1], outline='blue', width=4)
73
  return img
74
 
75
- def click_handler(evt: gr.SelectData, state):
76
- board, player, last_user, last_ai = state
77
- x, y = evt.index; cell = 360//8
78
- c, r = int(x//cell), int((y-cell)//cell)
79
- # invalid
80
- if not (0<=r<8 and 0<=c<8):
81
- yield board_to_image(board, last_user, last_ai, player), state
82
- return
83
- # user move
84
- if apply_move(board, r, c, player):
85
- last_user = (r, c); player = -player
86
- yield board_to_image(board, last_user, last_ai, player), state
87
- else:
88
- yield board_to_image(board, last_user, last_ai, player), state
89
  return
90
- # AI thinking indicator
91
- yield board_to_image(board, last_user, last_ai, player), (board, player, last_user, last_ai)
92
  time.sleep(2)
93
- # AI move
94
- ai_mv = choose_move(board, player)
95
- if ai_mv:
96
- apply_move(board, ai_mv[0], ai_mv[1], player)
97
- last_ai = ai_mv; player = -player
98
- yield board_to_image(board, last_user, last_ai, player), (board, player, last_user, last_ai)
99
- else:
100
- yield board_to_image(board, last_user, last_ai, player), (board, player, last_user, last_ai)
101
 
102
  with gr.Blocks() as demo:
103
- state = gr.State((initialize_board(), -1, None, None))
104
- board_img = gr.Image(value=board_to_image(initialize_board(), None, None, -1), interactive=True)
105
- board_img.select(click_handler, inputs=[state], outputs=[board_img, state])
 
 
106
  demo.launch()
 
1
  import gradio as gr
2
  from PIL import Image, ImageDraw, ImageFont
3
+ import random, time
 
4
 
5
+ # Game logic as before
6
+ DIRECTIONS = [(-1,-1),(-1,0),(-1,1),(0,-1),(0,1),(1,-1),(1,0),(1,1)]
 
7
 
8
  def initialize_board():
9
  b = [[0]*8 for _ in range(8)]
 
11
  b[3][4], b[4][3] = -1, -1
12
  return b
13
 
 
 
14
  def get_flips(board, r, c, p):
15
  if board[r][c] != 0: return []
16
+ flips=[]
17
+ for dr,dc in DIRECTIONS:
18
+ rr,cc=r+dr,c+dc; buf=[]
19
+ while 0<=rr<8 and 0<=cc<8 and board[rr][cc]==-p:
20
+ buf.append((rr,cc)); rr+=dr; cc+=dc
21
+ if buf and 0<=rr<8 and 0<=cc<8 and board[rr][cc]==p:
22
+ flips+=buf
23
  return flips
24
 
25
  def apply_move(board, r, c, p):
26
+ f=get_flips(board,r,c,p)
27
  if not f: return False
28
+ board[r][c]=p
29
+ for rr,cc in f: board[rr][cc]=p
30
  return True
31
 
32
+ def choose_move(board, player):
33
+ valid=[(r,c) for r in range(8) for c in range(8) if get_flips(board,r,c,player)]
34
+ return random.choice(valid) if valid else None
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 is_game_over(board):
42
+ if any(get_flips(board,r,c,p) for p in [-1,1] for r in range(8) for c in range(8)): return False
43
+ return True
44
+
45
+ # Image renderer
46
+ FONT = ImageFont.truetype("arial.ttf", 24)
47
 
48
+ def board_to_image(board, state):
49
+ board, player, last_user, last_ai, history = state
50
+ size=360; cell=size//8
51
+ img=Image.new('RGB',(size,size+cell*2),'darkgreen')
52
+ draw=ImageDraw.Draw(img)
53
+ # Scoreboard top
54
+ b,w=count_score(board)
55
+ draw.rectangle([0,0,size,cell],fill='navy')
56
+ draw.text((10,2),f"BLACK: {b}",font=FONT,fill='white')
57
+ draw.text((size-160,2),f"WHITE: {w}",font=FONT,fill='white')
58
+ # Game end highlight
59
+ if is_game_over(board):
60
+ winner = "Draw" if b==w else ("Black Wins" if b>w else "White Wins")
61
+ draw.rectangle([0,cell,size,cell*2],fill='maroon')
62
+ draw.text((size//2-80,cell+2),winner,font=FONT,fill='yellow')
63
  # Board
64
  for r in range(8):
65
  for c in range(8):
66
+ x0,y0=c*cell,cell*2+r*cell; x1,y1=x0+cell,y0+cell
67
+ draw.rectangle([x0,y0,x1,y1],outline='black')
68
+ # candidate
69
+ if board[r][c]==0 and get_flips(board,r,c,player):
70
+ draw.ellipse([x0+cell*0.4,y0+cell*0.4,x0+cell*0.6,y0+cell*0.6],fill='yellow')
71
+ if board[r][c]==1: draw.ellipse([x0+4,y0+4,x1-4,y1-4],fill='white')
72
+ if board[r][c]==-1: draw.ellipse([x0+4,y0+4,x1-4,y1-4],fill='black')
 
 
 
73
  # markers
74
+ for mark,clr in ((state[2],'red'),(state[3],'blue')):
75
+ if mark:
76
+ mr,mc=mark; x0,y0=mc*cell,cell*2+mr*cell; x1,y1=x0+cell,y0+cell
77
+ draw.rectangle([x0,y0,x1,y1],outline=clr,width=4)
78
+ # history display
79
+ y=text_y=cell*2+8*cell+2
80
+ for i,res in enumerate(history[-5:]):
81
+ draw.text((10,y+i*(cell//2)),res,font=ImageFont.truetype("arial.ttf",16),fill='white')
82
  return img
83
 
84
+ # Handlers
85
+
86
+ def click_handler(evt,state):
87
+ board,player,lu,la,history=state
88
+ x,y=evt.index; cell=360//8; c,r=int(x//cell),int((y-cell*2)//cell)
89
+ if 0<=r<8 and 0<=c<8 and not is_game_over(board):
90
+ if apply_move(board,r,c,player): lu=(r,c); player=-player
91
+ yield board_to_image(board,(board,player,lu,la,history)),(board,player,lu,la,history)
92
+ if is_game_over(board):
93
+ history.append(f"Game {len(history)+1}: {'Black' if count_score(board)[0]>count_score(board)[1] else 'White' if count_score(board)[1]>count_score(board)[0] else 'Draw'}")
 
 
 
 
94
  return
95
+ # AI
96
+ yield board_to_image(board,(board,player,lu,la,history)),(board,player,lu,la,history)
97
  time.sleep(2)
98
+ ai_mv=choose_move(board,player)
99
+ if ai_mv: apply_move(board,ai_mv[0],ai_mv[1],player); la=ai_mv; player=-player
100
+ yield board_to_image(board,(board,player,lu,la,history)),(board,player,lu,la,history)
101
+
102
+ def reset_handler():
103
+ return initialize_board(),-1,None,None,[]
 
 
104
 
105
  with gr.Blocks() as demo:
106
+ state=gr.State((initialize_board(),-1,None,None,[]))
107
+ img=gr.Image(value=board_to_image(initialize_board(),(initialize_board(),-1,None,None,[])),interactive=True)
108
+ new_btn=gr.Button("New Game")
109
+ img.select(click_handler,inputs=[state],outputs=[img,state])
110
+ new_btn.click(fn=reset_handler,outputs=[state,img])
111
  demo.launch()