Extending snake in turtle graphics snake game
Question: So I'm working on a snake game in python's turtle graphics and I'm required to
use turtle. So Everything is working out fine except I just need the snake to
extend by one as it eats the objective. Can somebody please help.

    
    
    from turtle import *
    import random
    def snakeGame():
        setup(700, 700)
        title("Snake Game!")
        bgcolor("black")
    
        Radius = 10
    
        # Boundary
        bPen = Pen()
        bPen.ht()
        bPen.color("Green")
        bPen.up()
        bPen.goto(-300, -300)
        bPen.down()
    
        for i in range(4):
            bPen.ht()
            bPen.fd(600)
            bPen.lt(90)
    
    
        # Player 
        playerPen = Pen()
        playerPen.color("Green")
        playerPen.shape("square")
        playerPen.up()
        playerPen.width(4)
    
        # Create Circle
    
        square = Pen()
        square.shape("square")
        square.color("Yellow")
        square.up()
        square.speed(0)
        square.goto(-100, 100)
    
    
        # Speed
        speed = 2
    
        # Movement functions
    
        def up():
            playerPen.setheading(90)
    
        def down():
            playerPen.setheading(270)
    
        def left():
            playerPen.setheading(180)
    
        def right():
            playerPen.setheading(0)
    
    
    
    
        # Game Over
    
        def gameOver():
            pen = Pen()
            pen.ht()
            pen.color("white")
            pen.write("GAME OVER!", align = "center", font = ("courier", 25, "bold"))
    
        # Score
    
        scoreVal = 0
    
    
        # Key Prompts
        onkey(left, "Left")
        onkey(right, "Right")
        onkey(up, "Up")
        onkey(down, "Down")
        listen()
    
        # Infinity loop and game over 
        while True:
            playerPen.fd(speed)
    
            if playerPen.xcor() < -300 or playerPen.xcor() > 300:
                gameOver()
                playerPen.ht()
                score = "Score = " + str(scoreVal)
                sPen = Pen()
                sPen.up()
                sPen.ht()
                sPen.goto(0, -100)
                sPen.color("white")
                sPen.write(score, align = "center", font = ("courier", 18, "bold"))
    
            elif playerPen.ycor() < -300 or playerPen.ycor() > 300:
                gameOver()
                playerPen.ht()
                score = "Score = " + str(scoreVal)
                sPen = Pen()
                sPen.up()
                sPen.ht()
                sPen.goto(0, -100)
                sPen.color("white")
                sPen.write(score, align = "center", font = ("courier", 18, "bold"))
    
            # Collision with square
            r1 = square.xcor() + 15
            r2 = square.xcor() - 15
            r3 = square.ycor() + 15
            r4 = square.ycor() - 15
            if (playerPen.xcor() >= r2 and playerPen.xcor() <= r1) and (playerPen.ycor() >= r4 and playerPen.ycor() <= r3):
                square.goto(random.randint(-290, 290), random.randint(-290, 290))
                scoreVal += 1
                speed += 1
    
    
    
    snakeGame()
    done()
    


Answer: I've been working on this code for a while and the following is what I've come
up with.

    
    
    import turtle
    from random import randint
    
    SCREEN = turtle.Screen()
    SCREEN.title("Snake Game!")
    SCREEN.setup(700,200)
    SCREEN.bgcolor("black")
    
    game_difficulty = 0
    difficulty = turtle.Turtle()
    difficulty.up()
    difficulty.goto(0,-86.5)
    difficulty.color("white")
    difficulty.write("Choose the difficulty of the game:\n e for easy\n n for normal\n h for hard\n", align = "center", font = ("courier", 20, "bold"))
    
    def difficulty_easy():
        global game_difficulty
        game_difficulty = 250
    
    def difficulty_normal():
        global game_difficulty
        game_difficulty = 150
    
    def difficulty_hard():
        global game_difficulty
        game_difficulty = 85
    
    SCREEN.onkey(difficulty_easy, "e")
    SCREEN.onkey(difficulty_easy, "E")
    SCREEN.onkey(difficulty_normal, "n")
    SCREEN.onkey(difficulty_normal, "N")
    SCREEN.onkey(difficulty_hard, "h")
    SCREEN.onkey(difficulty_hard, "H")
    SCREEN.listen()
    
    while game_difficulty != 150 and game_difficulty != 250 and game_difficulty != 85:
        difficulty.ht()
    
    difficulty.clear()
    SCREEN.setup(700,700)  
    food = turtle.Turtle()
    food.up()
    food.shape("circle")
    food.shapesize(0.9)
    food.color("red")
    
    frame = turtle.Turtle()
    frame.ht()
    frame.speed(1000)
    frame.color("Green")
    frame.up()
    frame.goto(-310,-310)
    frame.down()
    for i in range (2):
        for i in range(31):
            frame.fd(20)
            frame.lt(90)
            frame.fd(620)
            frame.bk(620)
            frame.rt(90)
        frame.lt(90)
    for i in range(2):
        frame.fd(620)
        frame.lt(90)
    
    snake = turtle.Turtle()
    snake.up()
    snake.shape("square")
    snake.color("green")
    
    snake_coor = [(0,0)]
    
    stamps = []
    
    dir_x = 0
    dir_y = 0
    
    Move = 0    
    LastMove = 0
    
    stop = False
    
    def getRandPos(): 
        return ((randint(-15,15)*20,randint(-15,15)*20))
    
    def actualiseDisplay():
        tracer = SCREEN.tracer()
        SCREEN.tracer(0)
        snake.clearstamps(len(snake_coor))
        food.goto(food_coor[0],food_coor[1])
    
        for x,y in snake_coor:
            snake.goto(x,y)
            snake.stamp()
    
        SCREEN.tracer(tracer)
    
    def isSnakeAbove(random):
        global snake_coor
        times = 0
        random = random
        while times < len(snake_coor):
            while random == snake_coor[times]:
                random = ((randint(-15,15)*20,randint(-15,15)*20))
            times = times + 1
        return random
    
    food_coor = isSnakeAbove(getRandPos())
    
    def actualisePos():
        global snake_coor, food_coor, stop
        avance()
        if isSelfCollision() or isBorderCollision():
            stop = True
        if isFoodCollision():
            append()
            food_coor = isSnakeAbove(getRandPos()) 
    
    def loop():
        if stop:
            gameOver()
            return
        actualisePos()
        actualiseDisplay()
        SCREEN.ontimer(loop,game_difficulty)
    
    def isSelfCollision():
        global snake_coor, LastMove, Move
        if len(snake_coor) >= 2:
            if LastMove == 1 and Move == 2 or LastMove == 2 and Move == 1 or LastMove == 3 and Move == 4  or LastMove == 4 and Move == 3:
                return True
        return len(set(snake_coor)) < len(snake_coor)
    
    def isFoodCollision():
        sx,sy = snake_coor[0]
        fx,fy = food_coor
        if (sx >= fx - 10 and sx <= fx + 10) and (sy >= fy - 10 and sy <= fy + 10):
            return True 
    
    def isBorderCollision():
        x,y = snake_coor[0]   
        return not (-310 < x < 310 ) or not (-310 < y < 310 )
    
    def avance():
        global snake_coor
        x, y = snake_coor[0]
        x += dir_x*20
        y += dir_y*20
        snake_coor.insert(0, (x, y))
        snake_coor.pop(-1)
    
    def append():
        global snake_coor
        a = snake_coor[-1][:]
        snake_coor.append(a)
    
    def setDir(x,y):
        global dir_x, dir_y
        dir_x = x
        dir_y = y
    
    def right():
        global LastMove, Move
        LastMove = Move
        Move = 1
        setDir(1,0)
    
    def left():
        global LastMove, Move
        LastMove = Move
        Move = 2
        setDir(-1,0)
    
    def up():
        global LastMove, Move
        LastMove = Move
        Move = 3
        setDir(0,1)
    
    def down():
        global LastMove, Move
        LastMove = Move
        Move = 4
        setDir(0,-1)   
    
    def gameOver():
        d = turtle.Turtle()
        d.up()
        d.ht()
        d.goto(0,-20)
        d.color("white")
        snake.ht()
        snake.clearstamps(len(snake_coor))
        food.ht()
        frame.clear()
        SCREEN.setup(300 , 200)
        d.write("GAME OVER", align = "center", font = ("courier", 30, "bold"))
        d.goto(0,-40)
        G_O = "Score : "+str(len(snake_coor)-1)
        d.write(G_O, align = "center", font = ("courier", 20, "bold"))
        SCREEN.onclick(lambda*a:[SCREEN.bye(),exit()])
    
    SCREEN.onkey(up, "Up")
    SCREEN.onkey(down, "Down")
    SCREEN.onkey(right, "Right")
    SCREEN.onkey(left, "Left")
    SCREEN.listen()
    loop()
    turtle.mainloop()
    

