Python Snake The Complete Game
The complete game is the whole Snake program in one file. The file builds the board first and starts the game loop last.
The window and the border
The file opens with its name, its run line and its controls in a comment. The window and the border then set up the board.
# The game window
screen = turtle.Screen()
screen.setup(width=600, height=600)
screen.bgcolor("darkgreen")
screen.title("Snake")
screen.tracer(0)
# The border marks the edge of the board
border = turtle.Turtle()
border.speed(0)
border.color("white")
border.penup()
border.goto(-290, -290)
border.pendown()
for side in range(4):
border.forward(580)
border.left(90)
border.hideturtle()The head, the food and the score pen
The head, the food and the body list come next. The pen takes its place at the top of the board to write the score.
# The snake head
head = turtle.Turtle()
head.speed(0)
head.shape("square")
head.color("lime")
head.penup()
head.goto(0, 0)
head.direction = "right"
# The food: one red circle on the board
food = turtle.Turtle()
food.speed(0)
food.shape("circle")
food.color("red")
food.penup()
# The body starts empty; the scores start at zero
segments = []
score = 0
high_score = 0
delay = 0.1
paused = False
# The pen writes the score at the top of the board
pen = turtle.Turtle()
pen.speed(0)
pen.color("white")
pen.penup()
pen.hideturtle()
pen.goto(0, 260)Moving and steering
The move function steps the head 20 pixels in its current direction. The four go functions set that direction and block a turn back into the neck.
def move():
if head.direction == "up":
head.sety(head.ycor() + 20)
if head.direction == "down":
head.sety(head.ycor() - 20)
if head.direction == "left":
head.setx(head.xcor() - 20)
if head.direction == "right":
head.setx(head.xcor() + 20)
def go_up():
if head.direction != "down":
head.direction = "up"
def go_down():
if head.direction != "up":
head.direction = "down"
def go_left():
if head.direction != "right":
head.direction = "left"
def go_right():
if head.direction != "left":
head.direction = "right"The score and the reset
show_score clears the pen and writes the score line again. reset_game sends the head home, clears the body and starts the score again at zero.
def show_score():
pen.clear()
pen.write(f"Score: {score} High Score: {high_score}", align="center", font=("Courier", 20, "bold"))
def toggle_pause():
global paused
paused = not paused
def reset_game():
global score, high_score, delay
time.sleep(0.5)
head.goto(0, 0)
head.direction = "stop"
for segment in segments:
segment.hideturtle()
segments.clear()
if score > high_score:
high_score = score
score = 0
delay = 0.1
show_score()The keyboard and the game loop
The keys bind the steering, pause and restart functions to the keyboard. The loop then redraws the board and steps the game on every tick.
# The keyboard steers the snake
screen.listen()
screen.onkey(go_up, "Up")
screen.onkey(go_down, "Down")
screen.onkey(go_left, "Left")
screen.onkey(go_right, "Right")
screen.onkey(toggle_pause, "p")
screen.onkey(reset_game, "r")
# The game loop: redraw, step the game unless paused, wait, repeat
while True:
screen.update()
if not paused:
# The body follows: each segment takes the place of the one ahead
for index in range(len(segments) - 1, 0, -1):
x = segments[index - 1].xcor()
y = segments[index - 1].ycor()
segments[index].goto(x, y)
if len(segments) > 0:
segments[0].goto(head.xcor(), head.ycor())
move()
# Walls: the head left the board, so the run ends
if head.xcor() > 290 or head.xcor() < -290 or head.ycor() > 290 or head.ycor() < -290:
reset_game()
# Self: the head ran into the body, so the run ends
for segment in segments:
if segment.distance(head) < 20:
reset_game()
break
# Eat: the head reached the food
if head.distance(food) < 20:
new_food_spot()
new_segment = turtle.Turtle()
new_segment.speed(0)
new_segment.shape("square")
new_segment.color("lightgreen")
new_segment.penup()
segments.append(new_segment)
score = score + 10
if delay > 0.05:
delay = delay - 0.005
show_score()
time.sleep(delay)Example
# Snake - the classic arcade game, built lesson by lesson.
# Run it with: python snake.py
# Steer with the arrow keys. Press P to pause and R to restart.
import turtle
import time
import random
# The game window
screen = turtle.Screen()
screen.setup(width=600, height=600)
screen.bgcolor("darkgreen")
screen.title("Snake")
screen.tracer(0)
# The border marks the edge of the board
border = turtle.Turtle()
border.speed(0)
border.color("white")
border.penup()
border.goto(-290, -290)
border.pendown()
for side in range(4):
border.forward(580)
border.left(90)
border.hideturtle()
# The snake head
head = turtle.Turtle()
head.speed(0)
head.shape("square")
head.color("lime")
head.penup()
head.goto(0, 0)
head.direction = "right"
# The food: one red circle on the board
food = turtle.Turtle()
food.speed(0)
food.shape("circle")
food.color("red")
food.penup()
# The body starts empty; the scores start at zero
segments = []
score = 0
high_score = 0
delay = 0.1
paused = False
# The pen writes the score at the top of the board
pen = turtle.Turtle()
pen.speed(0)
pen.color("white")
pen.penup()
pen.hideturtle()
pen.goto(0, 260)
def move():
if head.direction == "up":
head.sety(head.ycor() + 20)
if head.direction == "down":
head.sety(head.ycor() - 20)
if head.direction == "left":
head.setx(head.xcor() - 20)
if head.direction == "right":
head.setx(head.xcor() + 20)
def go_up():
if head.direction != "down":
head.direction = "up"
def go_down():
if head.direction != "up":
head.direction = "down"
def go_left():
if head.direction != "right":
head.direction = "left"
def go_right():
if head.direction != "left":
head.direction = "right"
def new_food_spot():
x = random.randint(-14, 14) * 20
y = random.randint(-14, 14) * 20
food.goto(x, y)
def show_score():
pen.clear()
pen.write(f"Score: {score} High Score: {high_score}", align="center", font=("Courier", 20, "bold"))
def toggle_pause():
global paused
paused = not paused
def reset_game():
global score, high_score, delay
time.sleep(0.5)
head.goto(0, 0)
head.direction = "stop"
for segment in segments:
segment.hideturtle()
segments.clear()
if score > high_score:
high_score = score
score = 0
delay = 0.1
show_score()
new_food_spot()
show_score()
# The keyboard steers the snake
screen.listen()
screen.onkey(go_up, "Up")
screen.onkey(go_down, "Down")
screen.onkey(go_left, "Left")
screen.onkey(go_right, "Right")
screen.onkey(toggle_pause, "p")
screen.onkey(reset_game, "r")
# The game loop: redraw, step the game unless paused, wait, repeat
while True:
screen.update()
if not paused:
# The body follows: each segment takes the place of the one ahead
for index in range(len(segments) - 1, 0, -1):
x = segments[index - 1].xcor()
y = segments[index - 1].ycor()
segments[index].goto(x, y)
if len(segments) > 0:
segments[0].goto(head.xcor(), head.ycor())
move()
# Walls: the head left the board, so the run ends
if head.xcor() > 290 or head.xcor() < -290 or head.ycor() > 290 or head.ycor() < -290:
reset_game()
# Self: the head ran into the body, so the run ends
for segment in segments:
if segment.distance(head) < 20:
reset_game()
break
# Eat: the head reached the food
if head.distance(food) < 20:
new_food_spot()
new_segment = turtle.Turtle()
new_segment.speed(0)
new_segment.shape("square")
new_segment.color("lightgreen")
new_segment.penup()
segments.append(new_segment)
score = score + 10
if delay > 0.05:
delay = delay - 0.005
show_score()
time.sleep(delay)Key points
- The window is 600 by 600, dark green, and titled Snake
- The white border marks the square from -290 to 290
- The head starts at the centre and the food is one red circle
- The arrow keys steer the head and the snake cannot reverse
- Each bite adds one body segment and 10 points to the score
- A wall hit or a bite into the body resets the run
- The P key pauses the game and the R key restarts the run
In this example, the file starts with a short comment that names the game, gives the run line and lists the controls. The imports bring in turtle, time and random. The window opens at 600 by 600 with a dark green board and the title Snake. The border turtle draws the white square from -290 to 290. The head starts at the centre facing right, and the food waits as one red circle. The score variables start at zero and the delay starts at 0.1. The pen moves to the top of the board to write the score. The functions then define movement, steering, food spots, the score line, pause and reset. The first food spot and the first score line are set before the keyboard bindings. The loop redraws the board on every tick. Inside a tick the body follows, the head moves, and the wall, body and food checks run in that order. A bite adds a segment, adds 10 points and trims the delay. The sleep at the end of the tick sets the pace of the game.
Try it Yourself
Edit the code, then press Run.
Running is simulated
Exercise
In the complete game, what happens when the head crosses the wall line?