Spec Sheet — Snake (Python Turtle Edition)
Project File: snake.py
Difficulty: Beginner / Intermediate
Must Have: Movement, Food, Growth, Collisions, Score
Goal
Build the classic Snake game where the player controls a snake that grows when it eats food. The game ends when the snake hits a wall or itself.
Requirements
Game Window
- Create a window (recommended: 600x600).
- Use a dark background for contrast.
- Title the window: “Snake”
Snake
- Snake is made of square segments.
- Starts with 3 segments.
- Moves continuously in one direction (default: right).
- Arrow keys change direction (Up, Down, Left, Right).
- No direct reverse: if moving right, cannot instantly go left.
Food
- Food appears at a random location on the screen grid.
- When snake head touches food:
- Score increases by 1
- Food respawns somewhere new
- Snake grows by 1 segment
Collisions
- Wall collision → Game Over
- Self collision (head touches any body segment) → Game Over
Scoreboard
- Display score at top of screen.
- Update live as score changes.
- Show “GAME OVER” on collision.
Controls
- ⬆️ Up Arrow = move up
- ⬇️ Down Arrow = move down
- ⬅️ Left Arrow = move left
- ➡️ Right Arrow = move right
Optional Enhancements: High score, speed increases, restart button, sound effects.
Pseudocode
START program
SET screen size, title, and background
CREATE scoreboard and display score = 0
CREATE snake as a list of 3 segments
SET snake direction to RIGHT
CREATE food at a random position
DEFINE function move_snake():
FOR each segment from tail to head:
move segment to the position of the segment in front of it
move head forward by MOVE_DISTANCE
DEFINE function go_up():
IF current direction is not DOWN:
set direction to UP
DEFINE function go_down():
IF current direction is not UP:
set direction to DOWN
DEFINE function go_left():
IF current direction is not RIGHT:
set direction to LEFT
DEFINE function go_right():
IF current direction is not LEFT:
set direction to RIGHT
BIND arrow keys to direction functions
LOOP forever:
update screen
pause for a short time
move_snake()
IF head touches food:
increase score
update scoreboard
respawn food randomly
add new segment to snake tail
IF head hits wall:
display GAME OVER
stop loop
IF head hits any body segment:
display GAME OVER
stop loop
END program
Rubric (100 Points)
| Category | Excellent (Full Credit) | Points |
|---|---|---|
| Program Runs / No Crashes | Game runs without errors; clean exit/game over | 15 |
| Snake Movement | Continuous movement; smooth segment following | 15 |
| Controls & No Reverse Rule | Arrow keys work; cannot reverse into itself instantly | 10 |
| Food Spawn & Eating | Food spawns randomly on grid; collision detection works | 15 |
| Growth Mechanic | Snake grows correctly by 1 segment per food | 10 |
| Scoring | Score increases correctly; displayed and updates live | 10 |
| Wall Collision | Game ends when snake hits boundary | 10 |
| Self Collision | Game ends when snake hits its body | 10 |
| Code Quality | Meaningful names, comments, organized sections/classes | 5 |
| Style / UX Polish | Clear colors, readable text, good window layout | 5 |
| Total | 100 |
Actual Python Code — snake.py
"""
File: snake.py
Classic Snake Game (Turtle)
Controls:
- Arrow keys to move
Rules:
- Eat food to grow and score points
- Crash into wall or yourself -> Game Over
"""
import time
import random
import turtle
# ----------------------------
# CONFIG
# ----------------------------
SCREEN_WIDTH = 600
SCREEN_HEIGHT = 600
MOVE_DISTANCE = 20
STARTING_SEGMENTS = 3
DELAY = 0.10 # lower = faster
UP = 90
DOWN = 270
LEFT = 180
RIGHT = 0
# ----------------------------
# SCOREBOARD
# ----------------------------
class Scoreboard(turtle.Turtle):
def __init__(self):
super().__init__()
self.score = 0
self.hideturtle()
self.penup()
self.color("white")
self.goto(0, SCREEN_HEIGHT // 2 - 40)
self.update_score()
def update_score(self):
self.clear()
self.write(f"Score: {self.score}", align="center", font=("Arial", 18, "normal"))
def add_point(self):
self.score += 1
self.update_score()
def game_over(self):
self.goto(0, 0)
self.write("GAME OVER", align="center", font=("Arial", 28, "bold"))
# ----------------------------
# FOOD
# ----------------------------
class Food(turtle.Turtle):
def __init__(self):
super().__init__()
self.shape("circle")
self.color("red")
self.penup()
self.speed(0)
self.shapesize(stretch_wid=0.7, stretch_len=0.7)
self.respawn()
def respawn(self):
# Keep food inside the walls
max_x = (SCREEN_WIDTH // 2) - 40
max_y = (SCREEN_HEIGHT // 2) - 60
# Snap to grid so it lines up with snake movement
x = random.randrange(-max_x, max_x + 1, MOVE_DISTANCE)
y = random.randrange(-max_y, max_y + 1, MOVE_DISTANCE)
self.goto(x, y)
# ----------------------------
# SNAKE
# ----------------------------
class Snake:
def __init__(self):
self.segments = []
self.direction = RIGHT
self._create_starting_snake()
def _create_starting_snake(self):
start_x = 0
for i in range(STARTING_SEGMENTS):
self._add_segment((start_x - i * MOVE_DISTANCE, 0))
def _add_segment(self, position):
seg = turtle.Turtle("square")
seg.color("lime")
seg.penup()
seg.goto(position)
self.segments.append(seg)
@property
def head(self):
return self.segments[0]
def grow(self):
# Add new segment at last segment position
tail = self.segments[-1]
self._add_segment(tail.position())
def move(self):
# Move each segment to the position of the one ahead
for idx in range(len(self.segments) - 1, 0, -1):
new_x = self.segments[idx - 1].xcor()
new_y = self.segments[idx - 1].ycor()
self.segments[idx].goto(new_x, new_y)
# Move head forward in current direction
self.head.setheading(self.direction)
self.head.forward(MOVE_DISTANCE)
# Direction controls (prevent reversing)
def up(self):
if self.direction != DOWN:
self.direction = UP
def down(self):
if self.direction != UP:
self.direction = DOWN
def left(self):
if self.direction != RIGHT:
self.direction = LEFT
def right(self):
if self.direction != LEFT:
self.direction = RIGHT
# ----------------------------
# MAIN GAME
# ----------------------------
def main():
screen = turtle.Screen()
screen.setup(width=SCREEN_WIDTH, height=SCREEN_HEIGHT)
screen.bgcolor("black")
screen.title("Snake")
screen.tracer(0) # manual screen refresh
snake = Snake()
food = Food()
scoreboard = Scoreboard()
# Key bindings
screen.listen()
screen.onkey(snake.up, "Up")
screen.onkey(snake.down, "Down")
screen.onkey(snake.left, "Left")
screen.onkey(snake.right, "Right")
game_running = True
while game_running:
screen.update()
time.sleep(DELAY)
snake.move()
# 1) Food collision
if snake.head.distance(food) < 15:
food.respawn()
snake.grow()
scoreboard.add_point()
# 2) Wall collision
x = snake.head.xcor()
y = snake.head.ycor()
wall_limit_x = (SCREEN_WIDTH // 2) - 10
wall_limit_y = (SCREEN_HEIGHT // 2) - 10
if x > wall_limit_x or x < -wall_limit_x or y > wall_limit_y or y < -wall_limit_y:
game_running = False
scoreboard.game_over()
break
# 3) Self collision
for segment in snake.segments[1:]:
if snake.head.distance(segment) < 10:
game_running = False
scoreboard.game_over()
break
screen.update()
screen.mainloop()
if __name__ == "__main__":
main()
Run it: Save as
snake.py and run with python snake.py.
Turtle graphics opens a new window for the game.