import gradio as gr import random import numpy as np from PIL import Image, ImageDraw, ImageFont import os class SnakeAndLadderGame: def __init__(self): # Board size self.board_size = 10 self.total_cells = self.board_size * self.board_size # Initialize snakes and ladders 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 } # Player positions self.player_positions = [0, 0] # Two players starting at position 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 # Check if the player won 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!" # Check if the player landed on a snake 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]}" # Check if the player landed on a ladder 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) # Switch to the next player 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): # Create a new image 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() # Draw board grid for row in range(self.board_size): for col in range(self.board_size): # Determine cell number based on row (0-9 from bottom to top) if row % 2 == 0: # Even rows (0, 2, 4, 6, 8) go left to right cell_num = (self.board_size - 1 - row) * self.board_size + col + 1 else: # Odd rows (1, 3, 5, 7, 9) go right to left cell_num = (self.board_size - 1 - row) * self.board_size + (self.board_size - col) # Cell position x0 = col * cell_size + padding y0 = (self.board_size - 1 - row) * cell_size + padding x1 = x0 + cell_size y1 = y0 + cell_size # Alternate cell colors for better visualization cell_color = (220, 220, 220) if (row + col) % 2 == 0 else (240, 240, 240) # Highlight snake cells if cell_num in self.snakes: cell_color = (255, 200, 200) # Light red for snakes # Highlight ladder cells if cell_num in self.ladders: cell_color = (200, 255, 200) # Light green for ladders draw.rectangle([x0, y0, x1, y1], fill=cell_color, outline=(0, 0, 0)) # Draw cell number draw.text((x0 + 5, y0 + 5), str(cell_num), fill=(0, 0, 0), font=font) # Mark snakes if cell_num in self.snakes: draw.text((x0 + 5, y0 + 25), f"S→{self.snakes[cell_num]}", fill=(255, 0, 0), font=font) # Mark ladders if cell_num in self.ladders: draw.text((x0 + 5, y0 + 25), f"L→{self.ladders[cell_num]}", fill=(0, 128, 0), font=font) # Draw player positions player_colors = [(0, 0, 255), (255, 0, 0)] # Blue for Player 1, Red for Player 2 for idx, pos in enumerate(self.player_positions): if pos > 0: # Find the cell position for the player row = (self.board_size - 1) - ((pos - 1) // self.board_size) if row % 2 == 0: # Even rows go left to right col = (pos - 1) % self.board_size else: # Odd rows go right to left col = self.board_size - 1 - ((pos - 1) % self.board_size) # Draw player token 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() # Initialize game game = SnakeAndLadderGame() # Create Gradio interface 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]) # Launch the app if __name__ == "__main__": demo.launch()