|
import gradio as gr |
|
import random |
|
import numpy as np |
|
from PIL import Image, ImageDraw, ImageFont |
|
import os |
|
|
|
class SnakeAndLadderGame: |
|
def __init__(self): |
|
|
|
self.board_size = 10 |
|
self.total_cells = self.board_size * self.board_size |
|
|
|
|
|
self.snakes = { |
|
16: 6, |
|
47: 26, |
|
49: 11, |
|
56: 53, |
|
62: 19, |
|
64: 60, |
|
87: 24, |
|
93: 73, |
|
95: 75, |
|
98: 78 |
|
} |
|
|
|
self.ladders = { |
|
1: 38, |
|
4: 14, |
|
9: 31, |
|
21: 42, |
|
28: 84, |
|
36: 44, |
|
51: 67, |
|
71: 91, |
|
80: 100 |
|
} |
|
|
|
|
|
self.player_positions = [0, 0] |
|
self.current_player = 0 |
|
self.game_over = False |
|
self.winner = None |
|
self.last_move = "" |
|
|
|
def roll_dice(self): |
|
return random.randint(1, 6) |
|
|
|
def move_player(self, player_idx, steps): |
|
if self.game_over: |
|
return f"Game over! Player {self.winner + 1} has won!" |
|
|
|
old_position = self.player_positions[player_idx] |
|
new_position = old_position + steps |
|
|
|
|
|
if new_position >= 100: |
|
self.player_positions[player_idx] = 100 |
|
self.game_over = True |
|
self.winner = player_idx |
|
return f"Player {player_idx + 1} has won the game!" |
|
|
|
|
|
elif new_position in self.snakes: |
|
self.player_positions[player_idx] = self.snakes[new_position] |
|
return f"Player {player_idx + 1} got bitten by a snake and moved from {new_position} to {self.snakes[new_position]}" |
|
|
|
|
|
elif new_position in self.ladders: |
|
self.player_positions[player_idx] = self.ladders[new_position] |
|
return f"Player {player_idx + 1} climbed a ladder and moved from {new_position} to {self.ladders[new_position]}" |
|
|
|
else: |
|
self.player_positions[player_idx] = new_position |
|
return f"Player {player_idx + 1} moved from {old_position} to {new_position}" |
|
|
|
def play_turn(self): |
|
if self.game_over: |
|
return self.draw_board(), f"Game over! Player {self.winner + 1} has won!" |
|
|
|
dice_roll = self.roll_dice() |
|
move_message = self.move_player(self.current_player, dice_roll) |
|
|
|
|
|
self.current_player = (self.current_player + 1) % 2 |
|
|
|
status = f"Dice: {dice_roll}. {move_message}" |
|
if not self.game_over: |
|
status += f"\nPlayer {self.current_player + 1}'s turn next." |
|
|
|
return self.draw_board(), status |
|
|
|
def draw_board(self): |
|
|
|
cell_size = 60 |
|
board_width = self.board_size * cell_size |
|
board_height = self.board_size * cell_size |
|
padding = 20 |
|
|
|
img = Image.new('RGB', (board_width + 2*padding, board_height + 2*padding), color=(255, 255, 255)) |
|
draw = ImageDraw.Draw(img) |
|
|
|
try: |
|
font = ImageFont.truetype("arial.ttf", 16) |
|
except IOError: |
|
font = ImageFont.load_default() |
|
|
|
|
|
for row in range(self.board_size): |
|
for col in range(self.board_size): |
|
|
|
if row % 2 == 0: |
|
cell_num = (self.board_size - 1 - row) * self.board_size + col + 1 |
|
else: |
|
cell_num = (self.board_size - 1 - row) * self.board_size + (self.board_size - col) |
|
|
|
|
|
x0 = col * cell_size + padding |
|
y0 = (self.board_size - 1 - row) * cell_size + padding |
|
x1 = x0 + cell_size |
|
y1 = y0 + cell_size |
|
|
|
|
|
cell_color = (220, 220, 220) if (row + col) % 2 == 0 else (240, 240, 240) |
|
|
|
|
|
if cell_num in self.snakes: |
|
cell_color = (255, 200, 200) |
|
|
|
|
|
if cell_num in self.ladders: |
|
cell_color = (200, 255, 200) |
|
|
|
draw.rectangle([x0, y0, x1, y1], fill=cell_color, outline=(0, 0, 0)) |
|
|
|
|
|
draw.text((x0 + 5, y0 + 5), str(cell_num), fill=(0, 0, 0), font=font) |
|
|
|
|
|
if cell_num in self.snakes: |
|
draw.text((x0 + 5, y0 + 25), f"S→{self.snakes[cell_num]}", fill=(255, 0, 0), font=font) |
|
|
|
|
|
if cell_num in self.ladders: |
|
draw.text((x0 + 5, y0 + 25), f"L→{self.ladders[cell_num]}", fill=(0, 128, 0), font=font) |
|
|
|
|
|
player_colors = [(0, 0, 255), (255, 0, 0)] |
|
for idx, pos in enumerate(self.player_positions): |
|
if pos > 0: |
|
|
|
row = (self.board_size - 1) - ((pos - 1) // self.board_size) |
|
if row % 2 == 0: |
|
col = (pos - 1) % self.board_size |
|
else: |
|
col = self.board_size - 1 - ((pos - 1) % self.board_size) |
|
|
|
|
|
player_x = col * cell_size + padding + (cell_size // 2) + (idx * 10 - 5) |
|
player_y = (self.board_size - 1 - row) * cell_size + padding + (cell_size // 2) + 10 |
|
|
|
draw.ellipse([player_x - 10, player_y - 10, player_x + 10, player_y + 10], |
|
fill=player_colors[idx], outline=(0, 0, 0)) |
|
draw.text((player_x - 4, player_y - 8), str(idx + 1), fill=(255, 255, 255), font=font) |
|
|
|
return img |
|
|
|
def reset_game(): |
|
global game |
|
game = SnakeAndLadderGame() |
|
return game.draw_board(), "Game reset. Player 1's turn to roll the dice." |
|
|
|
def take_turn(): |
|
global game |
|
return game.play_turn() |
|
|
|
|
|
game = SnakeAndLadderGame() |
|
|
|
|
|
with gr.Blocks(title="Snake and Ladder Game") as demo: |
|
gr.Markdown("# Snake and Ladder Game") |
|
gr.Markdown("Roll the dice and make your way to 100 while avoiding snakes and climbing ladders!") |
|
|
|
with gr.Row(): |
|
with gr.Column(scale=2): |
|
board_display = gr.Image(game.draw_board(), label="Game Board") |
|
|
|
with gr.Column(scale=1): |
|
status_text = gr.Textbox(value="Welcome to Snake and Ladder Game! Player 1's turn to roll the dice.", |
|
label="Game Status", lines=5) |
|
|
|
roll_button = gr.Button("Roll Dice") |
|
reset_button = gr.Button("Reset Game") |
|
|
|
gr.Markdown("### Game Rules:") |
|
gr.Markdown(""" |
|
1. Two players take turns rolling a dice. |
|
2. Move your token according to the dice roll. |
|
3. If you land on a snake's head, you'll slide down to its tail. |
|
4. If you land on the bottom of a ladder, you'll climb up to the top. |
|
5. The first player to reach or exceed position 100 wins! |
|
""") |
|
|
|
roll_button.click(take_turn, inputs=[], outputs=[board_display, status_text]) |
|
reset_button.click(reset_game, inputs=[], outputs=[board_display, status_text]) |
|
|
|
|
|
if __name__ == "__main__": |
|
demo.launch() |