Snake Game in Python

Below is a simple implementation of the classic Snake Game in Python. Copy and paste this code and run it!

import pygame
import sys
import random

pygame.init()

WIDTH, HEIGHT = 300, 300
DOT_SIZE = 10
MAX_DOTS = 900
RANDOM_POS = 29
DELAY = 140

x = [0] * MAX_DOTS
y = [0] * MAX_DOTS

dots = 3
appleX = 0
appleY = 0

movingLeft = False
movingRight = True
movingUp = False
movingDown = False
inGame = True

timer = pygame.time.Clock()

class SnakeGame:
    def __init__(self):
        self.initialize_board()

    def initialize_board(self):
        self.background_color = (0, 0, 0)
        self.dot_colors = {
            'apple': (255, 0, 0),
            'snake_head': (0, 255, 0),
            'snake_body': (255, 255, 0)
        }
        self.locate_apple()
        self.timer = pygame.time.Clock()
        self.initialize_game()

    def initialize_game(self):
        for z in range(dots):
            x[z] = 50 - z * DOT_SIZE
            y[z] = 50
        self.timer.tick(DELAY)

    def draw_dot(self, surface, color, x, y):
        pygame.draw.rect(surface, color, (x, y, DOT_SIZE, DOT_SIZE))

    def display_game_over(self, surface):
        font = pygame.font.SysFont(None, 30)
        message = font.render('Game Over', True, (255, 255, 255))
        surface.blit(message, (WIDTH // 2 - 70, HEIGHT // 2))

    def check_apple(self):
        nonlocal dots
        if x[0] == appleX and y[0] == appleY:
            dots += 1
            self.locate_apple()

    def move(self):
        for z in range(dots, 0, -1):
            x[z] = x[z - 1]
            y[z] = y[z - 1]
        if movingLeft:
            x[0] -= DOT_SIZE
        if movingRight:
            x[0] += DOT_SIZE
        if movingUp:
            y[0] -= DOT_SIZE
        if movingDown:
            y[0] += DOT_SIZE

    def check_collision(self):
        nonlocal inGame
        for z in range(dots, 0, -1):
            if z > 4 and x[0] == x[z] and y[0] == y[z]:
                inGame = False
        if y[0] >= HEIGHT or y[0] < 0 or x[0] >= WIDTH or x[0] < 0:
            inGame = False
        if not inGame:
            self.timer.tick(0)

    def locate_apple(self):
        nonlocal appleX, appleY
        random_pos = random.randint(0, RANDOM_POS)
        appleX = random_pos * DOT_SIZE
        random_pos = random.randint(0, RANDOM_POS)
        appleY = random_pos * DOT_SIZE

    def draw(self, surface):
        if inGame:
            self.draw_dot(surface, self.dot_colors['apple'], appleX, appleY)
            for z in range(dots):
                if z == 0:
                    self.draw_dot(surface, self.dot_colors['snake_head'], x[z], y[z])
                else:
                    self.draw_dot(surface, self.dot_colors['snake_body'], x[z], y[z])
            pygame.display.flip()
        else:
            self.display_game_over(surface)

def main():
    screen = pygame.display.set_mode((WIDTH, HEIGHT))
    pygame.display.set_caption('Snake Game')

    snake_game = SnakeGame()

    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()

        keys = pygame.key.get_pressed()
        if keys[pygame.K_LEFT] and not movingRight:
            movingLeft = True
            movingUp = False
            movingDown = False
        if keys[pygame.K_RIGHT] and not movingLeft:
            movingRight = True
            movingUp = False
            movingDown = False
        if keys[pygame.K_UP] and not movingDown:
            movingUp = True
            movingRight = False
            movingLeft = False
        if keys[pygame.K_DOWN] and not movingUp:
            movingDown = True
            movingRight = False
            movingLeft = False

        snake_game.check_apple()
        snake_game.check_collision()
        snake_game.move()

        screen.fill(snake_game.background_color)
        snake_game.draw(screen)

        snake_game.timer.tick(15)

if __name__ == '__main__':
    main()