How To Create Snake Game in Python

In this short guide we will show you how to make a snake game for playing in your terminal using Python. The main prerequisites for this is Python installation in the system. At the end of the tutorial, the application should run without any additional steps.

To begin, verify that Python is installed and functioning correctly:

$ python3 --version
Python 3.13.1

Now let’s create a directory for our snake game

mkdir -p ~/snake_game && cd ~/snake_game

Now we’ll create a snake game implementation using Python’s curses library. The game will include:

  • Snake movement using arrow keys
  • Food generation
  • Score tracking
  • Game over conditions
  • Simple UI

The game will be terminal-based and include features like arrow key movement, score display, random food generation, collision detection, and game restart capabilities.

To start, add a snake_game.py file to the snake_game folder created earlier.

vim snake_game.py

Paste the following contents into the file.

#!/usr/bin/env python3
import curses
import random
import time

def main(stdscr):
    # Setup initial game state
    curses.curs_set(0)  # Hide cursor
    stdscr.timeout(100)  # Set input timeout (controls game speed)
    
    # Get terminal dimensions
    height, width = stdscr.getmaxyx()
    
    # Check if terminal is large enough
    if height < 10 or width < 30:
        stdscr.clear()
        stdscr.addstr(0, 0, "Terminal too small. Please resize.")
        stdscr.refresh()
        stdscr.getch()
        return
    
    # Create color pairs
    curses.start_color()
    curses.init_pair(1, curses.COLOR_GREEN, curses.COLOR_BLACK)  # Snake
    curses.init_pair(2, curses.COLOR_RED, curses.COLOR_BLACK)    # Food
    curses.init_pair(3, curses.COLOR_YELLOW, curses.COLOR_BLACK) # Score
    
    # Game boundaries (leave space for borders and score)
    game_height = height - 2
    game_width = width - 2
    
    # Display welcome message and instructions
    show_instructions(stdscr)
    
    while True:
        # Game variables
        snake = [[game_height // 2, game_width // 4]]  # Start with a single segment
        direction = curses.KEY_RIGHT
        food = generate_food(snake, game_height, game_width)
        score = 0
        
        # Draw initial game state
        draw_game(stdscr, snake, food, score, game_height, game_width)
        
        game_over = False
        while not game_over:
            # Get user input
            key = stdscr.getch()
            
            # Process key press
            if key == ord('q'):
                return  # Quit game
            elif key in [curses.KEY_UP, curses.KEY_DOWN, curses.KEY_LEFT, curses.KEY_RIGHT]:
                # Prevent 180-degree turns
                if (key == curses.KEY_UP and direction != curses.KEY_DOWN) or \
                   (key == curses.KEY_DOWN and direction != curses.KEY_UP) or \
                   (key == curses.KEY_LEFT and direction != curses.KEY_RIGHT) or \
                   (key == curses.KEY_RIGHT and direction != curses.KEY_LEFT):
                    direction = key
            
            # Calculate new head position
            head = snake[0].copy()
            if direction == curses.KEY_UP:
                head[0] -= 1
            elif direction == curses.KEY_DOWN:
                head[0] += 1
            elif direction == curses.KEY_LEFT:
                head[1] -= 1
            elif direction == curses.KEY_RIGHT:
                head[1] += 1
            
            # Add new head
            snake.insert(0, head)
            
            # Check if snake eats food
            if snake[0] == food:
                food = generate_food(snake, game_height, game_width)
                score += 10
                # Speed up game slightly after eating (decrease timeout value)
                new_timeout = max(50, 100 - (score // 20))
                stdscr.timeout(new_timeout)
            else:
                # Remove tail if no food eaten
                snake.pop()
            
            # Check for collisions with boundaries
            if (snake[0][0] <= 0 or snake[0][0] >= game_height or 
                snake[0][1] <= 0 or snake[0][1] >= game_width):
                game_over = True
            
            # Check for collisions with self
            if snake[0] in snake[1:]:
                game_over = True
            
            # Draw game state
            draw_game(stdscr, snake, food, score, game_height, game_width)
        
        # Game over screen
        if show_game_over(stdscr, score) == ord('r'):
            continue  # Restart game
        else:
            break  # Exit game

def draw_game(stdscr, snake, food, score, height, width):
    """Draw the game state on the screen"""
    stdscr.clear()
    
    # Draw borders
    for i in range(width + 1):
        stdscr.addch(0, i, '#')
        stdscr.addch(height, i, '#')
    for i in range(height + 1):
        stdscr.addch(i, 0, '#')
        stdscr.addch(i, width, '#')
    
    # Draw snake
    for i, segment in enumerate(snake):
        char = '@' if i == 0 else 'O'  # Different char for head
        stdscr.attron(curses.color_pair(1))
        stdscr.addch(segment[0], segment[1], char)
        stdscr.attroff(curses.color_pair(1))
    
    # Draw food
    stdscr.attron(curses.color_pair(2))
    stdscr.addch(food[0], food[1], '*')
    stdscr.attroff(curses.color_pair(2))
    
    # Draw score
    score_text = f"Score: {score}"
    stdscr.attron(curses.color_pair(3))
    stdscr.addstr(0, width - len(score_text) - 1, score_text)
    stdscr.attroff(curses.color_pair(3))
    
    stdscr.refresh()

def generate_food(snake, height, width):
    """Generate food at a random position not occupied by the snake"""
    while True:
        food = [random.randint(1, height - 1), random.randint(1, width - 1)]
        if food not in snake:
            return food

def show_instructions(stdscr):
    """Display game instructions to the player"""
    stdscr.clear()
    height, width = stdscr.getmaxyx()
    
    title = "SNAKE GAME"
    stdscr.attron(curses.A_BOLD)
    stdscr.addstr(height // 4, (width - len(title)) // 2, title)
    stdscr.attroff(curses.A_BOLD)
    
    instructions = [
        "Use arrow keys to move the snake",
        "Eat food (*) to grow and increase your score",
        "Avoid hitting the walls or yourself",
        "Press 'q' to quit at any time",
        "Press 'r' to restart after game over",
        "",
        "Press any key to start..."
    ]
    
    for i, line in enumerate(instructions):
        stdscr.addstr(height // 3 + i + 1, (width - len(line)) // 2, line)
    
    stdscr.refresh()
    stdscr.getch()

def show_game_over(stdscr, score):
    """Display game over screen and return key pressed"""
    stdscr.clear()
    height, width = stdscr.getmaxyx()
    
    game_over_text = "GAME OVER"
    stdscr.attron(curses.A_BOLD)
    stdscr.addstr(height // 3, (width - len(game_over_text)) // 2, game_over_text)
    stdscr.attroff(curses.A_BOLD)
    
    score_text = f"Your score: {score}"
    stdscr.addstr(height // 3 + 2, (width - len(score_text)) // 2, score_text)
    
    restart_text = "Press 'r' to restart or 'q' to quit"
    stdscr.addstr(height // 3 + 4, (width - len(restart_text)) // 2, restart_text)
    
    stdscr.refresh()
    
    # Wait for 'r' or 'q' key
    while True:
        key = stdscr.getch()
        if key in [ord('r'), ord('q')]:
            return key

if __name__ == "__main__":
    # Initialize curses and start game
    try:
        curses.wrapper(main)
    except KeyboardInterrupt:
        # Handle Ctrl+C gracefully
        pass
    finally:
        # Ensure terminal is reset properly
        curses.endwin()
        print("Thanks for playing Snake Game!")

Make the file executable:

chmod +x ~/snake_game/snake_game.py

The game is ready! It includes the following features:

  • Arrow key controls
  • Score tracking
  • Food collection
  • Collision detection
  • Color display
  • Game over screen with restart option
  • Clear instructions

Here’s how you can play it:

~/snake_game/snake_game.py
  • Use arrow keys (↑,↓,←,→) to control the snake
  • Collect the red ‘*‘ symbols to grow and increase your score
  • Avoid hitting the walls or your own tail
  • Press ‘q‘ to quit at any time
  • If you lose, press ‘r‘ to restart or ‘q‘ to quit

On quitting you will get the message:

Thanks for playing Snake Game!

Join our Linux and open source community. Subscribe to our newsletter for tips, tricks, and collaboration opportunities!

Recent Post

Unlock the Right Solutions with Confidence

At CloudSpinx, we don’t just offer services - we deliver clarity, direction, and results. Whether you're navigating cloud adoption, scaling infrastructure, or solving DevOps challenges, our seasoned experts help you make smart, strategic decisions with total confidence. Let us turn complexity into opportunity and bring your vision to life.

Leave a Comment

Your email address will not be published. Required fields are marked *

Related Post

Performing regular backups of your files in Linux operating systems is a critical part of personal data security and overall […]

The Linux tablets have gained popularity over the past few years. Linux tablets are known to be secure, robust, and […]

Julia is a high-performance, high-level technical computing language that has a syntax that is familiar to users of technical computing […]

Let's Connect

Unleash the full potential of your business with CloudSpinx. Our expert solutions specialists are standing by to answer your questions and tailor a plan that perfectly aligns with your unique needs.
You will get a response from our solutions specialist within 12 hours
We understand emergencies can be stressful. For immediate assistance, chat with us now

Contact CloudSpinx today!

Download CloudSpinx Profile

Discover the full spectrum of our expertise and services by downloading our detailed Company Profile. Simply enter your first name, last name, and email address.