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?
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.