I havent posted an article in a long time because of schoolwork so I thought I would free 2 hours today to quickly program snake and upload it. This is the result. Since my last post, I have been making progress on a course in web development where I’ve been learning HTML, CSS, JS and node.js where I have learnt how to run a proper server with endpoints and have a mongoose server attached onto it so expect future articles on web development. Furthermore, I am doing a free CourseEra machine learning course on CourseEra which has been very useful because it has built up from the knowledge I learnt from the Udacity machine learning course I did before which only touched on the basics on machine learning. Now, for snake:

import pygame
import time
import sys
import random

WIDTH = 800
ROWS= 20
WIN = pygame.display.set_mode((WIDTH, WIDTH))
WIN.fill((255, 255, 255))

WHITE= (255,255,255)
DARKGREEN=(130, 168, 131)
GREEN = (69, 252, 3)
RED = (252, 61, 3)
BLACK = (0,0,0)

class Snake:
def __init__(self):
self.length = 2
self.colour = GREEN
self.head = [random.randint(5,ROWS-5), random.randint(5,ROWS-5)]
self.tail = [self.head]
self.direction = 'BW'

def createTail(self):
x,y = self.head
self.tail.append([x-2, y])
self.tail.append([x - 3, y])
self.tail.append([x - 4, y])

def GameOver(self):
validate = [val > 20 or val < 0 for val in self.head]
if True in validate:
print("Out Of Bounds")

self.head = self.tail[0]
if self.head in self.tail[1:]:
print("You ate yourself!")

def update_snake(self, grid, apple):
x, y = self.tail[-1]
grid[x][y].colour = WHITE
tempgrid = self.tail[:-1]

if self.direction =='FD':
x,y = tempgrid[0]
if self.direction =='BW':
x, y = tempgrid[0]
tempgrid.insert(0, [x + 1, y])
if self.direction =='LFT':
x, y = tempgrid[0]
tempgrid.insert(0, [x , y - 1])
if self.direction =='RGHT':
x, y = tempgrid[0]
tempgrid.insert(0, [x , y + 1])
self.tail = tempgrid


if self.head == apple.position:
apple.Respawn(grid, ROWS, self.tail)
x,y = self.tail[-1]
if grid[x+1][y].colour == WHITE: self.tail.append([x+1,y])
elif grid[x + 1][y].colour == WHITE: self.tail.append([x - 1, y])
elif grid[x + 1][y].colour == WHITE: self.tail.append([x , y + 1])
elif grid[x + 1][y].colour == WHITE: self.tail.append([x , y - 1])

class Apple:
def __init__(self):
self.ate = False

def Respawn(self, grid, rows, exempt):
state = True
while state:
location = [random.randint(2,rows-2), random.randint(2,rows-2)]
if location not in exempt:
state = False

self.position = location

class Node:
def __init__(self, row, col, width):
self.row = row
self.col = col
self.x = int(row * width)
self.y = int(col * width)
self.colour = WHITE
self.occupied = None

def draw(self, WIN):
pygame.draw.rect(WIN, self.colour, (self.x, self.y, WIDTH / ROWS, WIDTH / ROWS))

def update_display(win, grid, rows, width, snake, apple):
x, y = snake.head
grid[x][y].colour = DARKGREEN
a,b = apple.position
for i in range(1,len(snake.tail)):
x,y = snake.tail[i]
grid[x][y].colour = GREEN
for row in grid:
for spot in row:
draw_grid(win, rows, width)

def make_grid(rows, width):
grid = []
gap = width// rows
for i in range(rows):
for j in range(rows):
node = Node(j,i, gap)
return grid

def draw_grid(win, rows, width):
gap = width // ROWS
for i in range(rows):
pygame.draw.line(win, BLACK, (0, i * gap), (width, i * gap))
for j in range(rows):
pygame.draw.line(win, BLACK, (j * gap, 0), (j * gap, width))

def main(WIN, WIDTH):
grid = make_grid(ROWS,WIDTH)
Player = Snake()
apple = Apple()
apple.Respawn(grid, ROWS, Player.tail )

run = False
while True:
for start in pygame.event.get():
if start.type ==pygame.QUIT:

if start.type == pygame.KEYDOWN:
run = True
print('Game Starts Now!!')

while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
elif pygame.key.get_pressed()[pygame.K_w] or pygame.key.get_pressed()[pygame.K_UP]:
Player.direction= 'FD'

elif pygame.key.get_pressed()[pygame.K_s] or pygame.key.get_pressed()[pygame.K_DOWN]:
Player.direction= 'BW'

elif pygame.key.get_pressed()[pygame.K_a] or pygame.key.get_pressed()[pygame.K_LEFT]:
Player.direction= 'LFT'

elif pygame.key.get_pressed()[pygame.K_d] or pygame.key.get_pressed()[pygame.K_RIGHT]:
Player.direction= 'RGHT'
Player.update_snake(grid, apple)
update_display(WIN, grid, ROWS, WIDTH, Player, apple)
update_display(WIN, grid, ROWS, WIDTH, Player, apple)

main(WIN, WIDTH)

As you can probably notice from the example image, I haven’t made a large deal about the graphics of the game because I don’t believe I needed to invest time into making images considering the 1.5 hour time limit i gave myself to make the program. This is built on top of prior code I had written for chess and the game of life as I use the grid system from those programs to make the operations and logic in the program simple.

Following the logic of the program should be relatively simple since none of the functions are relatively complex although I will comment that looking at the final code, I don’t think that the apple class was totally necessary because I only need to use one function inside of it.


  1. The main challenges in the game is getting the snakes shape to stay the same as in when we move the head of the snake forward, we need the rest of the snake to move with it. Therefore, logically I had to realise that the only 2 parts of the snake that actually change is the first and last element while the other elements are just the positions of the original snake shifted to the left right by 1.
  2. Getting the initial set up of the snake to work was also challenging because I had to set up the head of the snake and also the tail separately and make sure that no errors were caused from out of bound index errors or other errors
  3. Generally, I had to relearn pygame to create this game so that came as a challenge as i did need to review past notes on the game in order to get it all to work.

In the end however, I did have a lot of fun making this program and I think I managed to complete it in just over 1.5 hours which I am very happy with considering I didn’t need any guidance from a youtube video or website. I hope you find the source code useful!