hanzla commited on
Commit
a6c1693
·
verified ·
1 Parent(s): fb6745b

Add Snake Game implementation with Gradio UI

Browse files
Files changed (1) hide show
  1. app.py +152 -0
app.py ADDED
@@ -0,0 +1,152 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import numpy as np
3
+ import pygame
4
+ import random
5
+ from PIL import Image
6
+ import io
7
+
8
+ # Initialize pygame
9
+ pygame.init()
10
+
11
+ # Game settings
12
+ WIDTH, HEIGHT = 400, 400
13
+ CELL_SIZE = 20
14
+ GRID_WIDTH, GRID_HEIGHT = WIDTH // CELL_SIZE, HEIGHT // CELL_SIZE
15
+
16
+ # Colors
17
+ BLACK = (0, 0, 0)
18
+ GREEN = (0, 255, 0)
19
+ RED = (255, 0, 0)
20
+ WHITE = (255, 255, 255)
21
+
22
+ class SnakeGame:
23
+ def __init__(self):
24
+ self.reset_game()
25
+
26
+ def reset_game(self):
27
+ self.snake = [(GRID_WIDTH // 2, GRID_HEIGHT // 2)]
28
+ self.direction = (1, 0)
29
+ self.food = self.generate_food()
30
+ self.score = 0
31
+ self.game_over = False
32
+
33
+ def generate_food(self):
34
+ while True:
35
+ food = (random.randint(0, GRID_WIDTH - 1), random.randint(0, GRID_HEIGHT - 1))
36
+ if food not in self.snake:
37
+ return food
38
+
39
+ def move(self, new_direction):
40
+ if self.game_over:
41
+ return
42
+
43
+ # Prevent moving in the opposite direction
44
+ if (new_direction[0] * -1, new_direction[1] * -1) != self.direction:
45
+ self.direction = new_direction
46
+
47
+ # Move snake
48
+ head = self.snake[0]
49
+ new_head = (head[0] + self.direction[0], head[1] + self.direction[1])
50
+
51
+ # Check boundaries
52
+ if (new_head[0] < 0 or new_head[0] >= GRID_WIDTH or
53
+ new_head[1] < 0 or new_head[1] >= GRID_HEIGHT or
54
+ new_head in self.snake):
55
+ self.game_over = True
56
+ return
57
+
58
+ self.snake.insert(0, new_head)
59
+
60
+ # Check if food eaten
61
+ if new_head == self.food:
62
+ self.score += 1
63
+ self.food = self.generate_food()
64
+ else:
65
+ self.snake.pop()
66
+
67
+ def get_game_image(self):
68
+ # Create surface
69
+ surface = pygame.Surface((WIDTH, HEIGHT))
70
+ surface.fill(BLACK)
71
+
72
+ # Draw snake
73
+ for segment in self.snake:
74
+ rect = pygame.Rect(segment[0] * CELL_SIZE, segment[1] * CELL_SIZE,
75
+ CELL_SIZE, CELL_SIZE)
76
+ pygame.draw.rect(surface, GREEN, rect)
77
+
78
+ # Draw food
79
+ food_rect = pygame.Rect(self.food[0] * CELL_SIZE, self.food[1] * CELL_SIZE,
80
+ CELL_SIZE, CELL_SIZE)
81
+ pygame.draw.rect(surface, RED, food_rect)
82
+
83
+ # Convert to PIL Image
84
+ w, h = surface.get_size()
85
+ raw = pygame.image.tostring(surface, 'RGB')
86
+ pil_image = Image.frombytes('RGB', (w, h), raw)
87
+
88
+ return pil_image
89
+
90
+ def auto_move(self):
91
+ """Move snake automatically in current direction"""
92
+ if not self.game_over:
93
+ self.move(self.direction)
94
+ return self.get_game_image(), f"Score: {self.score}" + (" - GAME OVER" if self.game_over else "")
95
+
96
+ # Initialize game
97
+ game = SnakeGame()
98
+
99
+ def move_up():
100
+ game.move((0, -1))
101
+ return game.get_game_image(), f"Score: {game.score}" + (" - GAME OVER" if game.game_over else "")
102
+
103
+ def move_down():
104
+ game.move((0, 1))
105
+ return game.get_game_image(), f"Score: {game.score}" + (" - GAME OVER" if game.game_over else "")
106
+
107
+ def move_left():
108
+ game.move((-1, 0))
109
+ return game.get_game_image(), f"Score: {game.score}" + (" - GAME OVER" if game.game_over else "")
110
+
111
+ def move_right():
112
+ game.move((1, 0))
113
+ return game.get_game_image(), f"Score: {game.score}" + (" - GAME OVER" if game.game_over else "")
114
+
115
+ def restart_game():
116
+ game.reset_game()
117
+ return game.get_game_image(), f"Score: {game.score}"
118
+
119
+ def auto_play():
120
+ return game.auto_move()
121
+
122
+ # Create Gradio interface
123
+ with gr.Blocks(title="Snake Game") as demo:
124
+ gr.Markdown("# 🐍 Snake Game")
125
+ gr.Markdown("Use the buttons below to control the snake. Eat the red food to grow and increase your score!")
126
+
127
+ with gr.Row():
128
+ game_display = gr.Image(value=game.get_game_image(), width=400, height=400)
129
+
130
+ score_display = gr.Textbox(value=f"Score: {game.score}", label="Score", interactive=False)
131
+
132
+ with gr.Row():
133
+ gr.Button("⬆️", size="sm").click(move_up, outputs=[game_display, score_display])
134
+
135
+ with gr.Row():
136
+ gr.Button("⬅️", size="sm").click(move_left, outputs=[game_display, score_display])
137
+ gr.Button("⬇️", size="sm").click(move_down, outputs=[game_display, score_display])
138
+ gr.Button("➡️", size="sm").click(move_right, outputs=[game_display, score_display])
139
+
140
+ with gr.Row():
141
+ gr.Button("🔄 Restart", variant="secondary").click(restart_game, outputs=[game_display, score_display])
142
+ gr.Button("⏯️ Auto Play", variant="primary").click(auto_play, outputs=[game_display, score_display])
143
+
144
+ gr.Markdown("**Instructions:**")
145
+ gr.Markdown("- Use arrow buttons to move the snake")
146
+ gr.Markdown("- Eat red food to grow and score points")
147
+ gr.Markdown("- Don't hit walls or yourself!")
148
+ gr.Markdown("- Use 'Auto Play' to watch the snake move automatically")
149
+ gr.Markdown("- Click 'Restart' to start a new game")
150
+
151
+ if __name__ == "__main__":
152
+ demo.launch()