Spaces:
Sleeping
Sleeping
import gradio as gr | |
import numpy as np | |
from game_logic import my_agent, Configuration, Observation | |
def initialize_game(): | |
return np.zeros((6, 7), dtype=int) | |
def make_move(board, column, player): | |
"""Make a move on the board""" | |
for row in range(5, -1, -1): | |
if board[row][column] == 0: | |
board[row][column] = player | |
return board | |
return board | |
def format_board(board): | |
"""Convert board to player-friendly visualization""" | |
symbols = {0: "⚪", 1: "🔴", 2: "🟡"} | |
return [[symbols[cell] for cell in row] for row in board] | |
def check_winner(board): | |
"""Check if there's a winner""" | |
board = np.array(board) | |
def check_line(line): | |
return (len(line) >= 4 and | |
(any(np.all(line[i:i+4] == 1) for i in range(len(line)-3)) or | |
any(np.all(line[i:i+4] == 2) for i in range(len(line)-3)))) | |
# Horizontal | |
for row in board: | |
if check_line(row): | |
return True | |
# Vertical | |
for col in board.T: | |
if check_line(col): | |
return True | |
# Diagonals | |
for offset in range(-2, 4): | |
diag = np.diagonal(board, offset) | |
if check_line(diag): | |
return True | |
diag = np.diagonal(np.fliplr(board), offset) | |
if check_line(diag): | |
return True | |
return False | |
def play_game(board, col, state): | |
if state["game_over"]: | |
return board, "Game is over! Click 'New Game' to play again." | |
# Convert Dataframe to numpy array for game logic | |
board_array = np.array([[0 if cell == "⚪" else 1 if cell == "🔴" else 2 for cell in row] | |
for row in board.values.tolist()]) | |
# Player move | |
board_array = make_move(board_array, col, 1) | |
if check_winner(board_array): | |
state["game_over"] = True | |
return format_board(board_array), "You win! 🎉" | |
# AI move | |
config = Configuration({"rows": 6, "columns": 7, "inarow": 4}) | |
obs = Observation({"board": board_array.flatten().tolist(), "mark": 2}) | |
ai_col = my_agent(obs, config) | |
board_array = make_move(board_array, ai_col, 2) | |
if check_winner(board_array): | |
state["game_over"] = True | |
return format_board(board_array), "AI wins! 🤖" | |
return format_board(board_array), "Your turn!" | |
def create_ui(): | |
with gr.Blocks(css=css) as demo: | |
gr.Markdown("# Play Connect Four Against AI") | |
gr.Markdown(f"You are {SYMBOLS[PLAYER]}, AI is {SYMBOLS[AI]}") | |
state = gr.State({"game_over": False}) | |
with gr.Row(elem_classes="button-row"): | |
buttons = [gr.Button(str(i), size="sm") for i in range(BOARD_SIZE[1])] | |
board = gr.Dataframe( | |
value=format_board(initialize_game()), | |
interactive=False, | |
show_label=False, | |
headers=None, | |
wrap=True, | |
elem_id="board", | |
row_count=BOARD_SIZE[0], | |
col_count=BOARD_SIZE[1] | |
) | |
message = gr.Textbox(value="Your turn!", label="Status") | |
new_game = gr.Button("New Game") | |
def reset_game(): | |
state = {"game_over": False} | |
return format_board(initialize_game()), "Your turn!", state | |
new_game.click( | |
reset_game, | |
outputs=[board, message, state] | |
) | |
for i, button in enumerate(buttons): | |
button.click( | |
play_game, | |
inputs=[board, gr.Number(value=i, visible=False), state], | |
outputs=[board, message] | |
) | |
return demo | |
# CSS definition | |
css = """ | |
#board { | |
max-width: 400px; | |
margin: 20px auto; | |
} | |
#board table { | |
width: 100%; | |
table-layout: fixed; | |
} | |
#board td { | |
text-align: center; | |
font-size: 32px; | |
padding: 12px; | |
width: 14.28%; /* 100% / 7 columns */ | |
} | |
.button-row { | |
max-width: 400px; | |
margin: 0 auto; | |
display: flex; | |
justify-content: space-between; | |
gap: 10px; | |
} | |
.button-row button { | |
flex: 1; | |
min-width: 40px; | |
} | |
""" | |
demo = create_ui() | |
demo.launch() |