Building the Game Snake
The Final Project
In the previous unit, we covered game loops, state management, and collision detection. Now let's put it all together and build Snake.

The Snake Class
The snake is a series of connected segments. The head moves forward, and each body segment follows the one ahead of it. We need methods to move, change direction, and grow when eating food.
class Snake:
def __init__(self):
self.segments = []
self.create_snake()
self.head = self.segments[0]
def create_snake(self):
self.add_segment((0, 0), "green")
for i in range(2):
self.add_segment((-(i+1) * 20, 0))
def add_segment(self, position, color="grey"):
segment = turtle.Turtle("square")
segment.color(color)
segment.penup()
segment.goto(position)
self.segments.append(segment)
def extend(self):
self.add_segment(self.segments[-1].position())
def move(self):
for seg_num in range(len(self.segments) - 1, 0, -1):
x = self.segments[seg_num - 1].xcor()
y = self.segments[seg_num - 1].ycor()
self.segments[seg_num].goto(x, y)
self.segments[0].forward(20)
def up(self):
if self.head.heading() != 270:
self.head.setheading(90)
def down(self):
if self.head.heading() != 90:
self.head.setheading(270)
def left(self):
if self.head.heading() != 0:
self.head.setheading(180)
def right(self):
if self.head.heading() != 180:
self.head.setheading(0)
The direction methods check that you can't reverse directly into yourself. If you're heading up, you can't suddenly go down.
The Food Class
Food appears at random positions. When eaten, it moves somewhere new. By extending turtle.Turtle, we inherit all the drawing and positioning methods.
class Food(turtle.Turtle):
def __init__(self):
super().__init__()
self.shape("circle")
self.penup()
self.shapesize(stretch_len=0.5, stretch_wid=0.5)
self.color("blue")
self.speed("fastest")
self.refresh()
def refresh(self):
random_x = random.randint(-240, 240)
random_y = random.randint(-240, 240)
self.goto(random_x, random_y)
The Complete Game
Here's the full Snake game:
import turtle
import time
import random
class Snake:
def __init__(self):
self.segments = []
self.create_snake()
self.head = self.segments[0]
def create_snake(self):
self.add_segment((0, 0), "green")
for i in range(2):
self.add_segment((-(i+1) * 20, 0))
def add_segment(self, position, color="grey"):
segment = turtle.Turtle("square")
segment.color(color)
segment.penup()
segment.goto(position)
self.segments.append(segment)
def extend(self):
self.add_segment(self.segments[-1].position())
def move(self):
for seg_num in range(len(self.segments) - 1, 0, -1):
x = self.segments[seg_num - 1].xcor()
y = self.segments[seg_num - 1].ycor()
self.segments[seg_num].goto(x, y)
self.segments[0].forward(20)
def up(self):
if self.head.heading() != 270:
self.head.setheading(90)
def down(self):
if self.head.heading() != 90:
self.head.setheading(270)
def left(self):
if self.head.heading() != 0:
self.head.setheading(180)
def right(self):
if self.head.heading() != 180:
self.head.setheading(0)
class Food(turtle.Turtle):
def __init__(self):
super().__init__()
self.shape("circle")
self.penup()
self.shapesize(stretch_len=0.5, stretch_wid=0.5)
self.color("blue")
self.speed("fastest")
self.refresh()
def refresh(self):
random_x = random.randint(-240, 240)
random_y = random.randint(-240, 240)
self.goto(random_x, random_y)
# Set up the game window
screen = turtle.Screen()
screen.bgcolor("black")
screen.title("Snake Game")
screen.setup(width=600, height=600)
turtle.tracer(n=1, delay=17)
# Create game objects
snake = Snake()
food = Food()
delay = 0.3
# Handle user input
screen.listen()
screen.onkey(snake.up, "Up")
screen.onkey(snake.down, "Down")
screen.onkey(snake.left, "Left")
screen.onkey(snake.right, "Right")
# Score display
score = 0
score_display = turtle.Turtle()
score_display.color("white")
score_display.penup()
score_display.goto(0, 260)
score_display.hideturtle()
score_display.write(f"Score: {score}", align="center", font=("Arial", 24, "normal"))
def update_game():
global score, delay, running
snake.move()
# Check for collision with food
if snake.head.distance(food) < 15:
food.refresh()
snake.extend()
score += 10
score_display.clear()
score_display.write(f"Score: {score}", align="center", font=("Arial", 24, "normal"))
if delay >= 0.05:
delay -= 0.05
# Check for collision with wall
if abs(snake.head.xcor()) > 280 or abs(snake.head.ycor()) > 280:
game_over()
# Check for collision with tail
for segment in snake.segments[1:]:
if snake.head.distance(segment) < 10:
game_over()
def game_over():
global running
running = False
score_display.goto(0, 0)
score_display.color("red")
score_display.write("Game Over", align="center", font=("Arial", 36, "bold"))
# Game loop
running = True
while running:
update_game()
screen.update()
if delay > 0:
time.sleep(delay)
screen.mainloop()
Use the arrow keys to move, collect blue food to grow, and avoid the walls and your own tail. The game speeds up as your score increases.
What's Next
You've completed the Python tutorial series. Try extending the game: add levels, obstacles, or a high score system. Consider splitting the code into multiple files for better organization.
Happy coding!