I've started learning Python yesterday with the intention of studying machine learning. Before this, my experience with programming was exclusive to my first semester where I had a C course.

I decided to work towards a final objective: have an AI learn how to win the snake game. For that goal, I had to make the actual game. I didn't want to copy an already made game as I'm still learning. So with that in mind, I spent an entire night building my little snake game.

I would like the game to be as good as possible before I started the machine learning part, which is why I'm posting it here. My biggest problem right now is controlling the speed of the game. I achieved this by limiting the FPS number based on the current score but it seems like a cheap way to do it.

I divided the game in two files: vars.py where I define most variables and functions and snake.py with the actual game and a few other things. This is the way I was taught to program so if it's wrong or not done please feel free to point that out.

**vars.py**

```
import random
import math

width = 800
height = 600
BG = 255, 255, 255
FOOD_C = 128, 0, 0
BODY_C = 0, 0, 0
sqr_size = 10
SPEED = sqr_size

def dist(a, b):
    return math.sqrt((b.pos[0] - a.pos[0])**2 + (b.pos[1] - a.pos[1])**2)

def check_food(snake, food): #Check if food is eaten
    if dist(snake, food) > sqr_size:
        return False
    else:
        return True

def loser(snake, food): #Check if lost the game
    if snake.pos[0]<sqr_size or snake.pos[0]>width-sqr_size:
        return True
    if snake.pos[1]<sqr_size or snake.pos[1]>height-sqr_size:
        return True
    for i in snake.body[1:]:
        if i == snake.pos:
            return True

def game_speed(snake):
    if (10 + snake.score()//2)  < 30:
        return 10 + snake.score()//2
    else:
        return 30          

class Snake(object):
    def __init__(self):
        self.pos = [random.randint(1, (width-sqr_size)/10)*10,
                    random.randint(1, (height-sqr_size)/10)*10]
        self.mov = "UP"
        self.body = [self.pos[:]]

    def change_mov(self, key): #Decide where to move
        if key == "UP" and self.mov != "DOWN":
            self.mov = key
        if key == "DOWN" and self.mov != "UP":
            self.mov = key
        if key == "RIGHT" and self.mov != "LEFT":
            self.mov = key
        if key == "LEFT" and self.mov != "RIGHT":
            self.mov = key

    def score(self):
        return len(self.body)

    def move(self, eat): #Snake movement
        if self.mov == "UP": self.pos[1] = self.pos[1] - SPEED
        if self.mov == "DOWN": self.pos[1] = self.pos[1] + SPEED
        if self.mov == "LEFT": self.pos[0] = self.pos[0] - SPEED
        if self.mov == "RIGHT": self.pos[0] = self.pos[0] + SPEED
        self.body.insert(0, self.pos[:])
        if not eat:
           self.body.pop()

class Food(object):
    def __init__(self):
        self.pos = [random.randint(1, (width-sqr_size)/10)*10,
                    random.randint(1, (height-sqr_size)/10)*10]

```

**snake.py**

```
import pygame, sys
import vars

#Initialising pygame 
pygame.init()
pygame.font.init()
myfont = pygame.font.SysFont('Times New Roman', 30)
clock = pygame.time.Clock()
screen = pygame.display.set_mode((vars.width,vars.height))
pygame.display.update()

#Initialising variables
lost = False
eat = False
snake = vars.Snake()
food = vars.Food()
screen.fill(vars.BG)
key1 = "0"

def whatkey(event):
    if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                return "LEFT"
            if event.key == pygame.K_RIGHT:
                return "RIGHT"
            if event.key == pygame.K_UP:
                return "UP"
            if event.key == pygame.K_DOWN:
                return "DOWN"

while not lost:
    for event in pygame.event.get():
        if event.type == pygame.QUIT: 
            sys.exit()
        key1 = whatkey(event)

    #How the game works   
    snake.change_mov(key1)
    eat = vars.check_food(snake, food)
    snake.move(eat)
    if eat:
        food = vars.Food()
    lost = vars.loser(snake, food)

    #Screen drawings
    screen.fill(vars.BG)
    for i in snake.body:
        pygame.draw.circle(screen, vars.BODY_C, (i[0], i[1]), vars.sqr_size, 0)
    pygame.draw.circle(screen, vars.FOOD_C, (food.pos[0], food.pos[1]), vars.sqr_size, 0)
    pygame.display.set_caption("Snake. Your score is: {}".format(snake.score()))
    pygame.display.update()

    #Control of the game speed via fps
    #Not related to the SPEED variable. That is for movement  
    msElapsed = clock.tick(vars.game_speed(snake))            

#Lose screen
pygame.display.update()
screen.fill(vars.BG)
textsurface1 = myfont.render('You lost. Your score is:', False, (0, 0, 0))
textsurface2 = myfont.render("{}".format(snake.score()), False, (0, 0, 0))
screen.blit(textsurface1,(250, 200))
screen.blit(textsurface2,(380,280))
pygame.display.update()
while 1:
    for event in pygame.event.get():
        if event.type == pygame.QUIT: sys.exit()

```