How to Build a Snake Game in Python Using Pygame
The Snake Game is one of the most popular beginner-friendly game development projects. It teaches important programming concepts such as game loops, keyboard input, collision detection, score management, and event handling.
In this tutorial, we'll build a complete Snake Game using Python and the Pygame library. The game includes:
- Moving snake
- Random food generation
- Score counter
- Collision detection
- Game Over screen
- Restart option
- On-screen mouse control buttons
Prerequisites
Before starting, make sure Python is installed.
Note: The original, upstream Pygame project has not yet released official pre-compiled wheels for Python 3.14. If you attempt to install it via pip install pygame under Python 3.14, your build will likely fail with a metadata or local compilation error because the required C extensions are not pre-built for this version.
Recommended Option: Pygame Community Edition (Pygame-CE)
Install Pygame using:
pip install pygame
//For Python 3.14
pip install pygame-ce
Project Overview
The game window is divided into small square cells. The snake moves one cell at a time. Whenever it eats food:
- The snake grows longer.
- The score increases.
- New food appears at a random location.
The game ends if the snake:
- Hits the wall
- Hits its own body
Import Required Modules
import pygame
import random
pygame.init()
Explanation
- pygame creates the game window, graphics, keyboard input, and sounds.
- random places food at random positions.
- pygame.init() initializes every required Pygame module.
Create Game Constants
WIDTH, HEIGHT = 600, 400
CELL = 20
FPS = 10
Explanation
These constants define the game configuration.
| Constant | Description |
|---|---|
| WIDTH | Game window width |
| HEIGHT | Game window height |
| CELL | Size of each snake block |
| FPS | Game speed |
Define Colors
BLACK = (0,0,0)
GREEN = (0,255,0)
RED = (255,0,0)
WHITE = (255,255,255)
GRAY = (80,80,80)
RGB values are used to draw the snake, food, buttons, and text.
Create the Game Window
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Snake Game")
This creates the main window where everything is drawn.
Create the Clock
clock = pygame.time.Clock()
font = pygame.font.SysFont(None,30)
The clock controls the frame rate. The font object is used for displaying the score and game over message.
Create On-Screen Control Buttons
BUTTON_SIZE = 40
up_button = pygame.Rect(...)
down_button = pygame.Rect(...)
left_button = pygame.Rect(...)
right_button = pygame.Rect(...)
Why Use Buttons?
- Works with mouse clicks
- Useful for touch screens
- Makes the game easier to play without a keyboard
Generate Random Food
def spawn_food(snake):
while True:
x = random.randrange(0, WIDTH, CELL)
y = random.randrange(0, HEIGHT, CELL)
if [x, y] not in snake:
return [x, y]
How It Works
- Selects a random grid position.
- Checks whether the snake already occupies that cell.
- If the location is free, food is created there.
Reset the Game
def reset():
snake = [
[100,100],
[80,100],
[60,100]
]
direction = "RIGHT"
food = spawn_food(snake)
score = 0
return snake, direction, food, score
Whenever a new game starts, this function creates a fresh snake, score, direction, and food.
Main Game Loop
while running:
Every Pygame application continuously runs inside a game loop. Each iteration performs four important tasks:
- Read user input
- Update the game
- Draw everything
- Repeat
Keyboard Controls
The game listens for arrow keys.
if event.key == pygame.K_UP:
direction = "UP"
The snake cannot instantly move in the opposite direction because that would immediately collide with itself.
Mouse Controls
elif event.type == pygame.MOUSEBUTTONDOWN:
When the player clicks one of the arrow buttons, the direction changes.
- Up Button → Move Up
- Down Button → Move Down
- Left Button → Move Left
- Right Button → Move Right
Move the Snake
The snake's head moves one cell depending on the current direction.
head = snake[0].copy()
A copy of the head is created before updating its coordinates.
Collision Detection
The game checks whether the snake:
- Leaves the window
- Touches its own body
if head in snake:
game_over = True
Eating Food
if head == food:
score += 1
food = spawn_food(snake)
When the snake reaches the food:
- Score increases.
- The snake grows.
- New food appears randomly.
Drawing the Snake
pygame.draw.rect(
screen,
GREEN,
(segment[0], segment[1], CELL, CELL)
)
Each snake segment is drawn as a green square.
Drawing the Food
pygame.draw.rect(screen, RED,
(food[0], food[1], CELL, CELL))
The food is displayed as a red square.
Display the Score
score_text = font.render(
f"Score: {score}",
True,
WHITE
)
The current score is always shown at the top-left corner.
Draw On-Screen Buttons
Four rounded buttons are drawn using pygame.Rect() and pygame.draw.rect().
Arrow symbols are displayed using the font renderer.
Game Over Screen
When the player loses, the following message appears:
- GAME OVER
- Press SPACE to Restart
Pressing the Space key calls the reset() function to start a new game.
Complete Features
- Grid-based movement
- Keyboard controls
- Mouse controls
- Random food spawning
- Score tracking
- Snake growth
- Wall collision detection
- Self collision detection
- Restart functionality
- Clean and beginner-friendly code
Final Complete Source Code
import pygame
import random
pygame.init()
# -------------------------------
# Constants
# -------------------------------
WIDTH, HEIGHT = 600, 400
CELL = 20
FPS = 10
# Colors
BLACK = (0, 0, 0)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
WHITE = (255, 255, 255)
GRAY = (80, 80, 80)
# -------------------------------
# Create Window
# -------------------------------
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Snake Game")
clock = pygame.time.Clock()
font = pygame.font.SysFont(None, 30)
# -------------------------------
# Control Buttons
# -------------------------------
BUTTON_SIZE = 40
up_button = pygame.Rect(500, 230, BUTTON_SIZE, BUTTON_SIZE)
down_button = pygame.Rect(500, 320, BUTTON_SIZE, BUTTON_SIZE)
left_button = pygame.Rect(450, 275, BUTTON_SIZE, BUTTON_SIZE)
right_button = pygame.Rect(550, 275, BUTTON_SIZE, BUTTON_SIZE)
# -------------------------------
# Functions
# -------------------------------
def spawn_food(snake):
while True:
x = random.randrange(0, WIDTH, CELL)
y = random.randrange(0, HEIGHT, CELL)
if [x, y] not in snake:
return [x, y]
def reset():
snake = [
[100, 100],
[80, 100],
[60, 100]
]
direction = "RIGHT"
food = spawn_food(snake)
score = 0
return snake, direction, food, score
# -------------------------------
# Game Variables
# -------------------------------
snake, direction, food, score = reset()
running = True
game_over = False
# -------------------------------
# Game Loop
# -------------------------------
while running:
# ---------------------------
# Events
# ---------------------------
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN:
if game_over:
if event.key == pygame.K_SPACE:
snake, direction, food, score = reset()
game_over = False
else:
if event.key == pygame.K_UP and direction != "DOWN":
direction = "UP"
elif event.key == pygame.K_DOWN and direction != "UP":
direction = "DOWN"
elif event.key == pygame.K_LEFT and direction != "RIGHT":
direction = "LEFT"
elif event.key == pygame.K_RIGHT and direction != "LEFT":
direction = "RIGHT"
elif event.type == pygame.MOUSEBUTTONDOWN:
pos = pygame.mouse.get_pos()
if up_button.collidepoint(pos) and direction != "DOWN":
direction = "UP"
elif down_button.collidepoint(pos) and direction != "UP":
direction = "DOWN"
elif left_button.collidepoint(pos) and direction != "RIGHT":
direction = "LEFT"
elif right_button.collidepoint(pos) and direction != "LEFT":
direction = "RIGHT"
# ---------------------------
# Move Snake
# ---------------------------
if not game_over:
head = snake[0].copy()
if direction == "UP":
head[1] -= CELL
elif direction == "DOWN":
head[1] += CELL
elif direction == "LEFT":
head[0] -= CELL
elif direction == "RIGHT":
head[0] += CELL
# Collision
if (
head[0] < 0
or head[0] >= WIDTH
or head[1] < 0
or head[1] >= HEIGHT
or head in snake
):
game_over = True
else:
snake.insert(0, head)
if head == food:
score += 1
food = spawn_food(snake)
else:
snake.pop()
# ---------------------------
# Draw
# ---------------------------
screen.fill(BLACK)
# Food
pygame.draw.rect(screen, RED, (food[0], food[1], CELL, CELL))
# Snake
for segment in snake:
pygame.draw.rect(
screen,
GREEN,
(segment[0], segment[1], CELL, CELL)
)
# Score
score_text = font.render(f"Score: {score}", True, WHITE)
screen.blit(score_text, (10, 10))
# ---------------------------
# Draw Control Buttons
# ---------------------------
pygame.draw.rect(screen, GRAY, up_button, border_radius=8)
pygame.draw.rect(screen, GRAY, down_button, border_radius=8)
pygame.draw.rect(screen, GRAY, left_button, border_radius=8)
pygame.draw.rect(screen, GRAY, right_button, border_radius=8)
screen.blit(font.render("↑", True, WHITE), (510, 235))
screen.blit(font.render("↓", True, WHITE), (510, 325))
screen.blit(font.render("←", True, WHITE), (460, 280))
screen.blit(font.render("→", True, WHITE), (560, 280))
# ---------------------------
# Game Over
# ---------------------------
if game_over:
game_over_text = font.render("GAME OVER", True, WHITE)
restart_text = font.render("Press SPACE to Restart", True, WHITE)
screen.blit(
game_over_text,
(
WIDTH // 2 - game_over_text.get_width() // 2,
HEIGHT // 2 - 20,
),
)
screen.blit(
restart_text,
(
WIDTH // 2 - restart_text.get_width() // 2,
HEIGHT // 2 + 15,
),
)
pygame.display.flip()
clock.tick(FPS)
pygame.quit()
Output:
Possible Improvements
- Add background music
- Add sound effects
- Store high scores
- Add pause button
- Multiple difficulty levels
- Animated snake head
- Power-up items
- Obstacles
- Touch controls for mobile
- Game menu
Conclusion
Congratulations! You have built a complete Snake Game using Python and Pygame. Along the way, you learned how to create a game loop, handle keyboard and mouse input, detect collisions, generate random objects, update scores, and render graphics in real time. This project provides a strong foundation for building more advanced 2D games with Python.
Frequently Asked Questions (FAQ)
1. Is Pygame suitable for beginners?
Yes. Pygame is one of the easiest libraries for learning game development in Python.
2. Can I add sound effects?
Yes. You can use pygame.mixer.Sound() to play sound effects and background music.
3. Why does the snake move on a grid?
Grid-based movement simplifies collision detection and makes gameplay predictable.
4. How can I increase the game speed?
Increase the value of the FPS constant to make the snake move faster.
5. Can this game run on Windows, macOS, and Linux?
Yes. Pygame is cross-platform and works on all major desktop operating systems.

.webp)