Skip to content

Instantly share code, notes, and snippets.

@elisco-latour
Last active November 28, 2025 08:11
Show Gist options
  • Select an option

  • Save elisco-latour/0937063573002db2c97e669401ca707f to your computer and use it in GitHub Desktop.

Select an option

Save elisco-latour/0937063573002db2c97e669401ca707f to your computer and use it in GitHub Desktop.
Python Snake Game - PyGame Version
"""
SNAKE GAME - PYGAME VERSION
A graphical implementation of the classic Snake game using Pygame.
Controls: Arrow Keys to move, Q or ESC to quit
"""
import pygame
import random
import sys
# Initialize Pygame
pygame.init()
# Game Constants
GRID_SIZE = 15
CELL_SIZE = 30
WINDOW_WIDTH = GRID_SIZE * CELL_SIZE
WINDOW_HEIGHT = GRID_SIZE * CELL_SIZE + 60 # Extra space for score
FPS = 60
# Colors
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GREEN = (0, 255, 0)
DARK_GREEN = (0, 200, 0)
RED = (255, 0, 0)
YELLOW = (255, 255, 0)
GRAY = (128, 128, 128)
# Create the game window
screen = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT))
pygame.display.set_caption("🐍 Snake Game - Pygame")
clock = pygame.time.Clock()
font = pygame.font.Font(None, 24)
large_font = pygame.font.Font(None, 36)
class SnakeGame:
"""Main Snake Game class"""
def __init__(self):
"""Initialize the game state"""
self.snake_body = [[5, 5], [4, 5], [3, 5]] # Head at [5,5], body extending left
self.direction = [1, 0] # Moving right [x, y]
self.next_direction = [1, 0] # For buffering input
self.food_pos = [self.get_random_position()]
self.score = 0
self.game_running = True
self.game_over = False
self.move_count = 0
def get_random_position(self):
"""Get a random position for food that doesn't overlap with snake"""
while True:
pos = [random.randint(0, GRID_SIZE - 1), random.randint(0, GRID_SIZE - 1)]
if pos not in self.snake_body:
return pos
def handle_input(self):
"""Handle keyboard input"""
for event in pygame.event.get():
if event.type == pygame.QUIT:
return "quit"
if event.type == pygame.KEYDOWN:
# Quit controls
if event.key == pygame.K_q or event.key == pygame.K_ESCAPE:
return "quit"
# Restart control
if event.key == pygame.K_r and self.game_over:
return "restart"
# Direction controls (arrow keys)
if event.key == pygame.K_UP and self.direction[1] == 0:
self.next_direction = [0, -1]
elif event.key == pygame.K_DOWN and self.direction[1] == 0:
self.next_direction = [0, 1]
elif event.key == pygame.K_LEFT and self.direction[0] == 0:
self.next_direction = [-1, 0]
elif event.key == pygame.K_RIGHT and self.direction[0] == 0:
self.next_direction = [1, 0]
return "continue"
def update(self):
"""Update game logic"""
if self.game_over:
return
self.move_count += 1
# Update direction from buffered input
self.direction = self.next_direction
# Calculate new head position
current_head = self.snake_body[0]
new_head = [current_head[0] + self.direction[0], current_head[1] + self.direction[1]]
# Check for wall collision
if (new_head[0] < 0 or new_head[0] >= GRID_SIZE or
new_head[1] < 0 or new_head[1] >= GRID_SIZE):
self.game_over = True
self.game_running = False
return
# Check for self collision
if new_head in self.snake_body:
self.game_over = True
self.game_running = False
return
# Add new head
self.snake_body.insert(0, new_head)
# Check if ate food
if new_head == self.food_pos[0]:
self.score += 1
self.food_pos = [self.get_random_position()]
# Snake grows (don't remove tail)
else:
# Remove tail (snake stays same length)
self.snake_body.pop()
def draw(self):
"""Draw the game"""
screen.fill(BLACK)
# Draw grid
for x in range(0, WINDOW_WIDTH, CELL_SIZE):
pygame.draw.line(screen, GRAY, (x, 60), (x, WINDOW_HEIGHT), 1)
for y in range(60, WINDOW_HEIGHT, CELL_SIZE):
pygame.draw.line(screen, GRAY, (0, y), (WINDOW_WIDTH, y), 1)
# Draw snake
for i, segment in enumerate(self.snake_body):
x = segment[0] * CELL_SIZE
y = segment[1] * CELL_SIZE + 60
if i == 0:
# Draw head in bright green
pygame.draw.rect(screen, GREEN, (x + 2, y + 2, CELL_SIZE - 4, CELL_SIZE - 4))
pygame.draw.rect(screen, WHITE, (x + 2, y + 2, CELL_SIZE - 4, CELL_SIZE - 4), 2)
else:
# Draw body in darker green
pygame.draw.rect(screen, DARK_GREEN, (x + 3, y + 3, CELL_SIZE - 6, CELL_SIZE - 6))
pygame.draw.rect(screen, GREEN, (x + 3, y + 3, CELL_SIZE - 6, CELL_SIZE - 6), 1)
# Draw food
food = self.food_pos[0]
food_x = food[0] * CELL_SIZE
food_y = food[1] * CELL_SIZE + 60
pygame.draw.rect(screen, RED, (food_x + 2, food_y + 2, CELL_SIZE - 4, CELL_SIZE - 4))
pygame.draw.circle(screen, YELLOW, (food_x + CELL_SIZE // 2, food_y + CELL_SIZE // 2), CELL_SIZE // 4)
# Draw score and info
score_text = font.render(f"Score: {self.score} | Moves: {self.move_count}", True, WHITE)
screen.blit(score_text, (10, 10))
if self.game_over:
instructions = font.render("Arrow Keys to move | R to restart | Q or ESC to quit", True, GRAY)
else:
instructions = font.render("Arrow Keys to move | Q or ESC to quit", True, GRAY)
screen.blit(instructions, (10, 35))
# Draw game over message
if self.game_over:
overlay = pygame.Surface((WINDOW_WIDTH, WINDOW_HEIGHT))
overlay.set_alpha(200)
overlay.fill(BLACK)
screen.blit(overlay, (0, 0))
game_over_text = large_font.render("GAME OVER!", True, RED)
final_score_text = large_font.render(f"Final Score: {self.score}", True, WHITE)
restart_text = font.render("Press R to restart or Q to exit", True, YELLOW)
screen.blit(game_over_text, (WINDOW_WIDTH // 2 - game_over_text.get_width() // 2,
WINDOW_HEIGHT // 2 - 60))
screen.blit(final_score_text, (WINDOW_WIDTH // 2 - final_score_text.get_width() // 2,
WINDOW_HEIGHT // 2))
screen.blit(restart_text, (WINDOW_WIDTH // 2 - restart_text.get_width() // 2,
WINDOW_HEIGHT // 2 + 60))
pygame.display.flip()
def run(self):
"""Main game loop"""
print("🐍 Snake Game Started!")
print(f"Window size: {WINDOW_WIDTH}x{WINDOW_HEIGHT}")
print(f"Grid size: {GRID_SIZE}x{GRID_SIZE}")
print(f"Controls: Arrow Keys to move, R to restart, Q or ESC to quit")
running = True
while running:
input_result = self.handle_input()
if input_result == "quit":
if self.game_over:
print(f"πŸ’₯ GAME OVER!")
print(f"Final Score: {self.score}")
print(f"Total Moves: {self.move_count}")
running = False
elif input_result == "restart":
# Reset the game
self.__init__()
print("πŸ”„ Game restarted!")
else: # continue
self.update()
self.draw()
clock.tick(FPS)
pygame.quit()
sys.exit()
if __name__ == "__main__":
game = SnakeGame()
game.run()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment