Skip to content
Game-Developer
  • Home
  • Blog
  • Games
  • Game Engines
  • Programming
Game-Developer
Game-Developer
  • Home
  • Blog
  • Games
  • Game Engines
  • Programming
Game-Developer
  Blog  How to code Snake game in Python? Step-by-step guide for beginners (2027)
Blog

How to code Snake game in Python? Step-by-step guide for beginners (2027)

GameDevGameDev—October 16, 2026
FacebookX TwitterPinterestLinkedInTumblrRedditVKWhatsAppEmail

Coding the classic Snake game in Python is an absolute rite of passage for anyone learning how to program. It is the perfect beginner project because it teaches you core logic without overwhelming you with complex physics engines. Plus, building a snake game using Python just feels right. To keep things as accessible as possible, we are strictly using Python’s built-in graphics library, so we are completely avoiding pygame. This means you do not need to install any external packages—you can jump straight into the code.

Table of Contents

Toggle
  • Goal and gameplay of Snake
  • Game window and design plan
  • How to create game window with Python?
    • Creating Canvas
    • Centering window on screen
  • Tile class and drawing Snake
  • How to move Snake?
    • Move function and clearing frames
  • Food collision and growing Snake
  • Game over states and tracking score
    • How to display score?

Goal and gameplay of Snake

The game window features a moving snake and a solid red square representing the food. When you press an arrow key, the snake begins moving in that direction. Every time the snake collides with the red square (the food), it grows one segment longer. The objective is to see how massive you can grow the snake without crashing into the outer walls or eating your own tail. If you hit a wall or cross your own body, the screen flashes a game over message.

Game window and design plan

We are building a game window sized exactly at 625 pixels by 625 pixels. We divide this window into 25 rows and 25 columns. That means every single square—or tile—is exactly 25 pixels by 25 pixels. So, our tile size is 25. The math here is simple: 25 x 25 equals 625.

When we draw the snake, we assign it an x and y coordinate. The top-left corner is 0,0, and the bottom-right corner is 625,625. The snake starts precisely 5 tiles to the right and 5 tiles down. Because of this, its starting x and y position is not 5,5; it is 5 x 25, which equals 125,125. Every row and column number gets multiplied by the tile size of 25. I messed this math up on my first try, and my snake spawned completely off the screen, so keep your coordinates straight.

How to create game window with Python?

I use Visual Studio Code for this, but any code editor will work just fine. Create a brand new Python file and name it snake.py.

First, we import a couple of essential libraries:

  • tkinter: Used for our graphics. It is Python’s standard graphical user interface library.
  • random: Used to spawn the food in random locations every time it gets eaten.

In Python, we define constants using uppercase letters. We have 25 rows and 25 columns. The tile size is 25 pixels. The window width is calculated by multiplying the tile size by the number of rows, and the window height is the tile size multiplied by the number of columns.

For the window setup:

  • Open a window using window = tk.Tk().
  • Add a title using window.title("Snake").
  • Prevent the user from resizing it using window.resizable(False, False). I left this out once, and resizing the window completely broke the game grid.
  • Keep the window running using window.mainloop().

Now, you have a locked 625×625 window.

Creating Canvas

With the window ready, we build a canvas to draw on:

  • Use tkinter.Canvas.
  • Set the master as our window.
  • Set the BG (background color) to Black.
  • Set the width to window width, and height to window height.
  • Pack the canvas into the window using canvas.pack().
  • Call window.update().

To remove the annoying default borders:

  • Set border width to 0.
  • Set highlight thickness to 0.

This ensures there is absolutely no dead space between the width and height.

Centering window on screen

By default, the window opens in a random spot on your screen every time you run the code. To fix this and center it properly:

  • Grab the window dimensions using window.winfo_width() and window.winfo_height().
  • Grab the screen dimensions using window.winfo_screenwidth() and window.winfo_screenheight().
  • Calculate the X position: int(screen_width / 2 - window_width / 2)
  • Calculate the Y position: int(screen_height / 2 - window_height / 2)

Then apply it using window.geometry(). The format requires a specific string: width x height + x + y. An f-string is perfect for this: f"{window_width}x{window_height}+{window_x}+{window_y}". Now it pops up dead center every single time.

Tile class and drawing Snake

We build a Tile class to store the x and y positions for both the snake and the food. The class simply takes an x and y coordinate.

When starting the game:

  • Create the snake’s head with snake = Tile(5 * tile_size, 5 * tile_size).
  • Spawn the food exactly 10 tiles right and 10 tiles down with food = Tile(10 * tile_size, 10 * tile_size).

To render the snake, define a draw function. Inside this function, declare snake as global.

Use canvas.create_rectangle for the drawing. It requires these values:

  • Top-left corner x and y: snake.x, snake.y
  • Bottom-right corner x and y: snake.x + tile_size, snake.y + tile_size
  • fill color: lime green

To create an actual game loop, use window.after. This calls the draw function repeatedly every 100 milliseconds (1/10th of a second). This gives us a smooth 10 frames per second.

Use the exact same method to draw the food:

  • canvas.create_rectangle
  • food.x, food.y, food.x + tile_size, food.y + tile_size
  • fill color: red

How to move Snake?

To get the snake moving, we define velocity X and velocity Y. Velocity is simply the change in position over time. Initially, both are set to 0, so the snake stays perfectly still.

Add a key listener using window.bind to track keyboard inputs. We listen for a Key release event. When a key is released, it triggers the change direction function. This function takes an e parameter, where e stands for event.

Here is the directional logic:

  • Up arrow: velocity X = 0, velocity Y = -1
  • Down arrow: velocity X = 0, velocity Y = 1
  • Left arrow: velocity X = -1, velocity Y = 0
  • Right arrow: velocity X = 1, velocity Y = 0

Keep in mind:

  • Moving left is the negative X direction.
  • Moving right is the positive X direction.
  • Moving up is the negative Y direction.
  • Moving down is the positive Y direction.

Move function and clearing frames

We define a move function. Inside, declare snake as global.

We add the velocity X to the snake’s x position. You absolutely must multiply this by the tile size; otherwise, the snake creeps forward by a single pixel instead of a full grid tile. Apply the exact same math to the y position.

Call this move function inside your draw loop. Since draw runs 10 times a second, the snake moves continuously at 10 frames per second.

When you first test this, you will see a massive green streak across the screen. That is because the previous frames are not being cleared. To fix this technical glitch, drop canvas.delete("all") at the top of your draw loop to wipe the slate clean before rendering the next frame.

At this point, two major bugs appear:

  1. The snake can instantly reverse direction (e.g., going right, then immediately left), crushing its own head. We need to prevent this.
  2. The snake briefly turns invisible when sliding over the food. This happens because the food is drawn over the snake.

The fixes:

  • Draw the food first, then the snake. This layer ordering keeps the snake visible during collision.
  • Add logic to block reversing:
    • On Up key: ensure velocity Y != 1
    • On Down key: ensure velocity Y != -1
    • On Left key: ensure velocity X != 1
    • On Right key: ensure velocity X != -1

Food collision and growing Snake

We create a list named snake_body to store all the tail segments. These segments are Tile objects.

Inside the move function, check for a collision between the snake’s head and the food. The detection is simple: do their x and y coordinates match?

  • If snake.x == food.x and snake.y == food.y, we have a collision.

When they collide:

  • Append a new segment to the body: snake_body.append(Tile(food.x, food.y)).
  • Teleport the food to a random new location:
    • food.x = random.randint(0, columns - 1) * tile_size
    • food.y = random.randint(0, rows - 1) * tile_size
  • randint generates a random number between 0 and columns – 1. Since we have 25 tiles, the numbers range from 0 to 24. We then multiply by the tile size.

Add the snake body to the draw function:

  • Use a for tile in snake_body: loop.
  • Run canvas.create_rectangle(tile.x, tile.y, tile.x + tile_size, tile.y + tile_size, fill="lime green").

However, the body will just sit there while the head moves away. To make the tail follow the head, use this strategy:

  • Move the body starting from the very back segment.
  • Make every tile take the position of the tile directly in front of it.
  • Use a reverse loop: for i in range(len(snake_body) - 1, -1, -1).
  • If i == 0, this is the first segment right behind the head. Assign it the head’s exact x and y coordinates.
  • Otherwise, grab prev_tile = snake_body[i - 1] and assign the current tile’s x and y to match prev_tile.

Now, when the snake eats the food, the tail grows and perfectly slithers behind the head.

Game over states and tracking score

Create a variable named game_over and set it to False by default.

Inside the change direction function:

  • Add if game_over: return. This completely locks the controls once you lose.
  • Make sure to define game over, food, snake body, and score as global.

Inside the move function:

  • Add if game_over: return to instantly freeze the snake upon dying.

Here are the conditions for losing:

  1. Crashing into the outer walls:
    • snake.x < 0
    • snake.x >= window_width
    • snake.y < 0
    • snake.y >= window_height If any of these hit, set game_over = True and return.
  2. Crashing into its own body:
    • Run a for tile in snake_body: loop.
    • If snake.x == tile.x and snake.y == tile.y:, set game_over = True and return.

How to display score?

Create a score variable starting at 0. Every time you register a food collision, increment the score by 1.

Render the score directly onto the canvas:

  • If game over triggers:
    • Use canvas.create_text at x: window_width / 2, y: window_height / 2.
    • Font: Arial, font size: 20.
    • Text: game over (also display the final score).
    • fill: White.
  • While playing normally:
    • Use canvas.create_text at x: 30, y: 20.
    • Font: Arial, size: 10.
    • Text: Use an f-string for the score.
    • fill: White.

Since you are modifying the score variable during gameplay, you must define it as global. I missed this on my first run and Python threw a brutal “local variable score referenced before assignment” error that broke the loop.

FacebookX TwitterPinterestLinkedInTumblrRedditVKWhatsAppEmail

GameDev

20+ classic PopCap games from best to worst
How to learn C++? Tutorial for beginners (2027)
Related posts
  • Related posts
  • More from author
Blog

Game studios tier list 2027: best and worst developers ranked

October 16, 2026

Recent Posts

  • How to learn C++? Tutorial for beginners (2027)
  • How to code Snake game in Python? Step-by-step guide for beginners (2027)
  • 20+ classic PopCap games from best to worst
  • Game studios tier list 2027: best and worst developers ranked
  • What is a game engine?
Social networks
FacebookLikes
X TwitterFollowers
PinterestFollowers
InstagramFollowers
YoutubeSubscribers
VimeoSubscribers
Popular categories
  • Blog2
  • Games1
  • Game Engines1
  • Programming1

How to learn C++? Tutorial for beginners (2027)

October 16, 2026

How to code Snake game in Python? Step-by-step guide for beginners (2027)

October 16, 2026

20+ classic PopCap games from best to worst

October 16, 2026

Game studios tier list 2027: best and worst developers ranked

October 16, 2026

What is a game engine?

October 16, 2026

What is a game engine?

Game studios tier list 2027: best and worst developers ranked

20+ classic PopCap games from best to worst

How to code Snake game in Python? Step-by-step guide for beginners (2027)

How to learn C++? Tutorial for beginners (2027)

    © 2026 Game-Developer
    • About us
    • Contact
    • Privacy Policy