import gradio as gr from PIL import Image, ImageDraw def initialize_board(): board = [[0 for _ in range(8)] for _ in range(8)] board[3][3], board[4][4] = 1, 1 board[3][4], board[4][3] = -1, -1 return board DIRECTIONS = [(-1, -1), (-1, 0), (-1, 1), (0, -1), (0, 1), (1, -1), (1, 0), (1, 1)] def get_flips(board, row, col, player): if board[row][col] != 0: return [] flips = [] for dr, dc in DIRECTIONS: r, c = row + dr, col + dc buffer = [] while 0 <= r < 8 and 0 <= c < 8 and board[r][c] == -player: buffer.append((r, c)) r += dr c += dc if buffer and 0 <= r < 8 and 0 <= c < 8 and board[r][c] == player: flips.extend(buffer) return flips def apply_move(board, row, col, player): flips = get_flips(board, row, col, player) if not flips: return False board[row][col] = player for r, c in flips: board[r][c] = player return True def board_to_image(board, img_size=320): cell_size = img_size // 8 img = Image.new('RGB', (img_size, img_size), 'green') draw = ImageDraw.Draw(img) for r in range(8): for c in range(8): x0, y0 = c * cell_size, r * cell_size x1, y1 = x0 + cell_size, y0 + cell_size draw.rectangle([x0, y0, x1, y1], outline='black') if board[r][c] == 1: draw.ellipse([x0+4, y0+4, x1-4, y1-4], fill='white') elif board[r][c] == -1: draw.ellipse([x0+4, y0+4, x1-4, y1-4], fill='black') return img def count_score(board): black = sum(cell == -1 for row in board for cell in row) white = sum(cell == 1 for row in board for cell in row) return black, white def play_move(x, y, state): board, player = state img_size = 320 cell_size = img_size / 8 col, row = int(x // cell_size), int(y // cell_size) if not (0 <= row < 8 and 0 <= col < 8): return board_to_image(board), f"Click inside the board.", state if not apply_move(board, row, col, player): return board_to_image(board), f"Invalid move at ({row+1},{col+1})", state player = -player black_score, white_score = count_score(board) status = f"Black: {black_score} | White: {white_score} | {'Black' if player == -1 else 'White'} to move" return board_to_image(board), status, (board, player) def main(): with gr.Blocks() as demo: gr.HTML("

Othello (Reversi) Game

") state = gr.State((initialize_board(), -1)) image_box = gr.Image(value=board_to_image(initialize_board()), interactive=True, label="Click to place a stone") status = gr.Text(value="Black: 2 | White: 2 | Black to move", interactive=False) def click_handler(evt: gr.SelectData, state): return play_move(evt.index[0], evt.index[1], state) image_box.select(click_handler, inputs=[state], outputs=[image_box, status, state]) demo.launch() if __name__ == "__main__": main()