Renecto commited on
Commit
560b34b
·
verified ·
1 Parent(s): e8a8e3e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +71 -73
app.py CHANGED
@@ -1,9 +1,11 @@
1
- import time
2
- import random
3
  import gradio as gr
4
  from PIL import Image, ImageDraw, ImageFont
 
 
5
 
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,14 +13,16 @@ def initialize_board():
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
 
@@ -26,83 +30,77 @@ 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, p):
33
- moves = [(r,c) for r in range(8) for c in range(8) if get_flips(board,r,c,p)]
34
- return random.choice(moves) if moves else None
35
-
36
- def count_score(b):
37
- bl = sum(c==-1 for row in b for c in row)
38
- wh = sum(c==1 for row in b for c in row)
39
- return bl, wh
40
-
41
- def get_possible(board, p):
42
- return [(r,c) for r in range(8) for c in range(8) if get_flips(board,r,c,p)]
43
 
44
- def is_game_over(board):
45
- return not any(get_flips(board,r,c,p) for p in (-1,1) for r in range(8) for c in range(8))
46
-
47
- def board_to_image(state):
48
- board, player, last_user, last_ai = state
49
- size, bs = 400, 360; off = 20; cell = bs//8
50
- img = Image.new('RGB', (size, size), 'darkgreen')
51
  draw = ImageDraw.Draw(img)
52
- try: fnt = ImageFont.truetype('arial.ttf',28)
53
- except: fnt = ImageFont.load_default()
54
- bl, wh = count_score(board)
55
- draw.rectangle([0,0,size,off], fill='black')
56
- draw.text((10,2), f"Black: {bl}", font=fnt, fill='yellow')
57
- draw.text((size-140,2), f"White: {wh}", font=fnt, fill='yellow')
58
- for r,c in get_possible(board, player):
59
- x = off+c*cell+cell//2; y = off+r*cell+cell//2
60
- draw.ellipse([x-5,y-5,x+5,y+5], outline='blue', width=2)
61
  for r in range(8):
62
  for c in range(8):
63
- x0,y0 = off+c*cell, off+r*cell; x1,y1 = x0+cell, y0+cell
 
64
  draw.rectangle([x0,y0,x1,y1], outline='black')
65
- v = board[r][c]
66
- if v:
67
- color = 'white' if v==1 else 'black'
68
- draw.ellipse([x0+4,y0+4,x1-4,y1-4], fill=color)
69
- for pos,col in [(last_user,'red'), (last_ai,'orange')]:
70
- if pos:
71
- r,c = pos; x0,y0 = off+c*cell, off+r*cell; x1,y1 = x0+cell, y0+cell
72
- draw.rectangle([x0+2,y0+2,x1-2,y1-2], outline=col, width=4)
73
- if is_game_over(board):
74
- res = 'DRAW' if bl==wh else 'BLACK WINS' if bl>wh else 'WHITE WINS'
75
- draw.text((size//2-80,size//2-15), res, font=fnt, fill='cyan')
 
 
 
 
 
76
  return img
77
 
78
- def click_handler(evt, state):
79
- if state is None:
80
- state = (initialize_board(), -1, None, None)
81
  board, player, last_user, last_ai = state
82
- x, y = evt.index[0], evt.index[1]
83
- cell = 360//8; off = 20
84
- c = int((x-off)//cell); r = int((y-off)//cell)
85
- if 0<=r<8 and 0<=c<8 and not is_game_over(board):
86
- if apply_move(board, r, c, player):
87
- last_user = (r, c); player = -player
88
- time.sleep(1)
89
- if not is_game_over(board):
90
- mv = choose_move(board, player)
91
- if mv:
92
- apply_move(board, mv[0], mv[1], player)
93
- last_ai = mv; player = -player
94
- new_state = (board, player, last_user, last_ai)
95
- return board_to_image(new_state), new_state
96
-
97
- def reset_game():
98
- state = (initialize_board(), -1, None, None)
99
- return board_to_image(state), state
 
 
 
 
 
 
100
 
101
- demo = gr.Blocks()
102
- with demo:
103
  state = gr.State((initialize_board(), -1, None, None))
104
- img = gr.Image(value=board_to_image((initialize_board(),-1,None,None)), interactive=True)
105
- new = gr.Button('New Game')
106
- img.select(click_handler, inputs=[state], outputs=[img, state], show_progress=True)
107
- new.click(reset_game, outputs=[img, state])
108
- 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
+ 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
  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
 
 
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"Black: {b}", font=font, fill='yellow')
50
+ draw.text((size-80,2), f"White: {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()