Skip to main content

Building the Game Snake

The Final Project

· 4 min read

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

Building the Game 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!