# Grid-based game concept
GRID_SIZE = 20 # Each square is 20x20 pixels
GRID_WIDTH = 800 // GRID_SIZE # 40 squares wide
GRID_HEIGHT = 600 // GRID_SIZE # 30 squares tall
print(f"Grid: {GRID_WIDTH}x{GRID_HEIGHT} = {GRID_WIDTH * GRID_HEIGHT} total squares")
# Snake position in grid coordinates
snake_x = 10 # 10 squares from left
snake_y = 15 # 15 squares from top
# Convert to pixel coordinates
pixel_x = snake_x * GRID_SIZE # 200 pixels
pixel_y = snake_y * GRID_SIZE # 300 pixels
print(f"Grid position ({snake_x}, {snake_y}) = Pixel position ({pixel_x}, {pixel_y})")Chapter 2.3: Building Snake Game - Part 1
Create the Classic Snake Game - Fundamentals
๐ฎ PROJECT 2.3 | Difficulty: Intermediate | Time: 25 minutes
๐ป Interactive Options:
- ๐ Open in JupyterLite
- ๐ฅ Download Notebook (Challenge) - For use in local Jupyter or Google Colab
- ๐ก Note: Pygame runs best locally with a display, but weโll show examples!
๐ Game Design: Snake
Goal: Control a snake, eat food, grow longer, avoid hitting walls or yourself
Game Mechanics:
- Snake moves continuously in one direction
- Arrow keys change direction
- Eating food makes snake grow
- Game over if snake hits wall or itself
๐ Grid-Based Movement
Snake uses a grid system. Instead of pixel-by-pixel movement, the snake moves in blocks:
๐ฎ Snake Data Structure
The snake is a list of positions:
# Snake as a list of (x, y) positions
# Head is at index 0, tail is at the end
snake = [
(10, 15), # Head
(9, 15), # Body segment
(8, 15), # Body segment
(7, 15), # Tail
]
print("๐ Snake structure:")
for i, segment in enumerate(snake):
if i == 0:
print(f" Head: {segment}")
elif i == len(snake) - 1:
print(f" Tail: {segment}")
else:
print(f" Body: {segment}")
# Moving the snake: add new head, remove tail
direction = (1, 0) # Moving right
head_x, head_y = snake[0]
new_head = (head_x + direction[0], head_y + direction[1])
snake.insert(0, new_head) # Add new head
snake.pop() # Remove tail
print(f"\nAfter moving right:")
print(f" New snake: {snake}")๐ฏ Complete Snake Game - Basic Version
# snake_game.py
import pygame
import random
import sys
pygame.init()
# Constants
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
GRID_SIZE = 20
GRID_WIDTH = SCREEN_WIDTH // GRID_SIZE
GRID_HEIGHT = SCREEN_HEIGHT // GRID_SIZE
FPS = 10 # Slower for easier gameplay
# Colors
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
# Initialize display
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("Snake Game")
clock = pygame.time.Clock()
# Snake starts in the middle
snake = [(GRID_WIDTH // 2, GRID_HEIGHT // 2)]
direction = (1, 0) # Start moving right
next_direction = direction
# Food position
def spawn_food():
while True:
food = (random.randint(0, GRID_WIDTH - 1),
random.randint(0, GRID_HEIGHT - 1))
if food not in snake:
return food
food = spawn_food()
score = 0
# Game loop
running = True
while running:
# Handle events
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP and direction != (0, 1):
next_direction = (0, -1)
elif event.key == pygame.K_DOWN and direction != (0, -1):
next_direction = (0, 1)
elif event.key == pygame.K_LEFT and direction != (1, 0):
next_direction = (-1, 0)
elif event.key == pygame.K_RIGHT and direction != (-1, 0):
next_direction = (1, 0)
# Update direction
direction = next_direction
# Move snake
head_x, head_y = snake[0]
new_head = (head_x + direction[0], head_y + direction[1])
# Check wall collision
if (new_head[0] < 0 or new_head[0] >= GRID_WIDTH or
new_head[1] < 0 or new_head[1] >= GRID_HEIGHT):
print(f"Game Over! Score: {score}")
running = False
continue
# Check self collision
if new_head in snake:
print(f"Game Over! Score: {score}")
running = False
continue
# Add new head
snake.insert(0, new_head)
# Check if ate food
if new_head == food:
score += 1
food = spawn_food()
else:
snake.pop() # Remove tail if didn't eat
# Draw everything
screen.fill(BLACK)
# Draw snake
for segment in snake:
rect = pygame.Rect(
segment[0] * GRID_SIZE,
segment[1] * GRID_SIZE,
GRID_SIZE - 1,
GRID_SIZE - 1
)
pygame.draw.rect(screen, GREEN, rect)
# Draw food
food_rect = pygame.Rect(
food[0] * GRID_SIZE,
food[1] * GRID_SIZE,
GRID_SIZE - 1,
GRID_SIZE - 1
)
pygame.draw.rect(screen, RED, food_rect)
# Draw score
font = pygame.font.Font(None, 36)
score_text = font.render(f'Score: {score}', True, WHITE)
screen.blit(score_text, (10, 10))
pygame.display.flip()
clock.tick(FPS)
pygame.quit()
sys.exit()๐ Key Concepts Explained
Direction Control
# Why we check opposite direction
print("๐ฎ Direction Logic:")
print("If moving RIGHT (1, 0), can't immediately go LEFT (-1, 0)")
print("If moving UP (0, -1), can't immediately go DOWN (0, 1)")
print("\nThis prevents the snake from reversing into itself!")
# Direction vectors
directions = {
"UP": (0, -1),
"DOWN": (0, 1),
"LEFT": (-1, 0),
"RIGHT": (1, 0)
}
for name, vector in directions.items():
print(f"{name}: {vector}")Collision Detection
# Two types of collisions in Snake
# 1. Wall collision
def check_wall_collision(position, grid_width, grid_height):
x, y = position
return (x < 0 or x >= grid_width or
y < 0 or y >= grid_height)
# 2. Self collision
def check_self_collision(head, body):
return head in body
# Examples
print("Wall Collision Examples:")
print(f" (-1, 5) hits wall: {check_wall_collision((-1, 5), 40, 30)}")
print(f" (20, 15) safe: {check_wall_collision((20, 15), 40, 30)}")
print("\nSelf Collision Examples:")
snake_body = [(5, 5), (5, 6), (5, 7)]
print(f" Head at (5, 5): {check_self_collision((5, 5), snake_body[1:])}")
print(f" Head at (5, 8): {check_self_collision((5, 8), snake_body)}")๐ Practice Challenges
Challenge 1: Add Features
Enhance the game with:
- Display game over screen instead of just closing
- Add restart functionality (press R to restart)
- Show high score that persists between games
Challenge 2: Visual Improvements
- Draw the snake head differently from body
- Add a grid background
- Make food blink or animate
- Add border around the play area
Challenge 3: Gameplay Variations
- Walls: Add obstacles in the middle
- Power-ups: Special food that gives bonus points
- Speed increase: Game gets faster as score increases
๐ Whatโs Next?
In the next slide, weโll complete the Snake game with:
- Restart functionality
- Score persistence
- Visual improvements
- Sound effects (optional)