Snake not following properly

97 Views Asked by At

I'm trying to remake the game Snake (in Python) just for fun, but I ran into a bug and can't figure out how to fix it. The snake head moves correctly, can eat the food, and add a new piece to the body. However, the body doesn't follow properly.

I use http://www.codeskulptor.org/ to program since I'm a student and we can't download things on our school computers.

The code doesn't run into any errors when you run it, but when you eat food, the body is created but just gets thrown on top of the head or disappears.

I'm not sure where the problem in my code is. First, when you eat something, the code runs the eat function, which appends a piece to the snake in the opposite direction of travel. Then, if the time is correct, it runs the move function. This runs through the snake from the end to the front, and makes a piece equal to the piece in front of it. Then, it moves the head forward, so I'm not sure what happens to the body.

Could someone help me out?

import simplegui, time, random

startTime = False
direction = None
snake = [[212.5, 212.5]]

def draw(canvas):
    global snake, food
    canvas.draw_polygon([(food[0] - 11, food[1] - 11), (food[0] + 11, food[1] - 11), (food[0] + 11, food[1] + 11), (food[0] - 11, food[1] + 11)], 1, 'red', 'red')
    for coords in snake:
        canvas.draw_polygon([(coords[0] - 11, coords[1] - 11), (coords[0] + 11, coords[1] - 11), (coords[0] + 11, coords[1] + 11), (coords[0] - 11, coords[1] + 11)], 1, 'green', 'green')
    if (snake[0] == food):
        eat()
    if (not startTime and direction != None):
        move()
    else:
        if (time.time() - startTime > 0.19 and time.time() - startTime < 0.23):
            move()

def key_handler(key):
    if (key == 37):
        left()
    elif (key == 38):
        up()
    elif (key == 39):
        right()
    elif (key == 40):
        down()

def move():
    global snake, direction, startTime
    for x in range(len(snake) - 1, 0, -1):
        snake[x] = snake[x-1]
    if (direction[0] == 0):
        snake[0][0] += direction[1]
    else:
        snake[0][1] += direction[1]
    startTime = time.time()

def eat():
    global snake, direction, food
    food = relocate()
    if (direction[0] == 0):
        snake.append([snake[len(snake) - 1][0] - direction[1], snake[len(snake) - 1][1]])
    else:
        snake.append([snake[len(snake) - 1][0], snake[len(snake) - 1][1] - direction[1]])

def relocate():
    global snake
    location = [random.randrange(13, 413, 25) - .5, random.randrange(13, 413, 25) - .5]
    for coords in snake:
        if (location == coords):
            location = relocate()
            break
    return location

def left():
    global direction
    direction = [0, -25]

def up():
    global direction
    direction = [1, -25]


def right():
    global direction
    direction = [0, 25]

def down():
    global direction
    direction = [1, 25]

food = relocate()

frame = simplegui.create_frame('Snake', 425, 425)
frame.set_keydown_handler(key_handler)
frame.set_draw_handler(draw)
frame.start()

Update: Codeskulptor has this mode called Viz mode where you can run through your code step by step. Using this code:

snake = [[212.5, 212.5], [212.5, 237.5]]
direction = [0, 25]
for x in range(len(snake) - 1, 0, -1):
    snake[x] = snake[x-1]
if (direction[0] == 0):
    snake[0][0] += direction[1]
else:
    snake[0][1] += direction[1]
print (snake)

in viz mode shows that when the body moves forward to the head, they become the same list, so when you move the head, it sets the body to the head's position since they're the same array. Is this a problem in my code or is this just the way Codeskulptor runs?

2

There are 2 best solutions below

0
On BEST ANSWER

The problem is that the head is stored as a list in memory, and then the body is set to that list also (the same memory slot) or at least that's what Codeskulptor is doing?? so instead of setting the body location equal to the head location, I set the body x equal to the head x and the body y equal to the head y and it worked.

0
On

I made some corrections: https://py3.codeskulptor.org/#user304_7fINP16ZAD_0.py

The major bug was the reuse of the same coordinates list. The snake is a list of lists of coordinates. When you copy a list (of coordinates) it is the same list, not a copy. So you have to explicitely copy it. Like I do in line 33 in the above code.