Здравствуйте.
Написал тривиальную змейку на Python, вроде все ок, кроме такого бага:
Когда "голова" змеи кушает первое яблоко, добавляеться новый сегмент, но его координаты соответствуют координатам "головы", в итоге я получаю, что есть два сегмента с одними и теме же координатами. При добавлении следующих сегментов все ок, не могу понять в чем проблема.
Прикрепляю ниже полный код.
from tkinter import *
import random,shelve
# import shelve for saving highscore
class Game:
# BASIC VARIABLES
width = 700
height = 500
apple_size = 20
field_color = 'black'
score_1 = 0
highscore = shelve.open('highscore')['highscore']
segments = []
# VARIABLES AND FUNCTIONS FOR CHANGING DIRECTION
move_left = -apple_size, 0
move_right = apple_size, 0
move_top = 0, -apple_size
move_down = 0, apple_size
direction = move_right
def __init__(self):
#PLAY
self.root = Tk()
self.root.title('Snake')
self.field = Canvas(self.root, width=self.width, height=self.height, bg=self.field_color)
self.field.pack()
self.field.focus_set()
self.score = Label(self.root, text='Your score: {}. Best score: {}'.format(self.score_1, self.highscore))
self.score.pack(side='bottom', anchor='w')
def change_top(self):
self.direction = self.move_top
def change_down(self):
self.direction = self.move_down
def change_left(self):
self.direction = self.move_left
def change_right(self):
self.direction = self.move_right
def create_segment(self):
b = self.field.coords(self.segments[0])[:]
if self.direction == self.move_right:
for x in (0, 2):
b[x]-=20
elif self.direction == self.move_down:
for x in(1,3):
b[x]-=20
elif self.direction == self.move_top:
for x in(1,3):
b[x]+=20
else:
for x in (0, 2):
b[x]+=20
new_segment=self.field.create_rectangle(*b, fill='white')
self.segments.insert(0,new_segment)
def game_over(self):
if self.score_1 > self.highscore:
shelve.open('highscore')['highscore'] = self.score_1
self.field.create_text(self.width / 2, self.height / 2, text="GAME OVER!", font="Helvetica 20", fill="white")
self.field.after(1500, lambda: self.root.quit())
def create_apple(self):
self.posx = random.randint(1,self.width/self.apple_size-1)*self.apple_size
self.posy = random.randint(1,self.height/self.apple_size-1)*self.apple_size
for x in range(len(self.segments)):
if [self.posx,self.posy,self.posx+self.apple_size,self.posy+self.apple_size] ==\
self.field.coords(self.segments[x]):
self.create_apple()
self.apple = self.field.create_rectangle(self.posx,self.posy,self.posx+self.apple_size,self.posy+self.apple_size,fill = 'red')
def create_snake(self):
self.snake = self.field.create_rectangle(20,20,40,40,fill = 'blue')
self.segments.append(self.snake)
def start(): #MOVING
for x in range(len(self.segments)):
self.a = self.field.coords(self.segments[x-1])
print(len(self.segments))
self.a[0]+=self.direction[0]
self.a[1]+=self.direction[1]
self.a[2]=self.a[0]+self.apple_size
self.a[3]=self.a[1]+self.apple_size
if x == 0:
self.field.coords(self.segments[x-1], self.a )
else:
self.field.coords(self.segments[x-1],*self.field.coords(self.segments[x]))
if self.field.coords(self.segments[-1]) == self.field.coords(self.apple): # IF SNAKE'S EATEN AN APPLE
self.score_1+=1
self.score.config(text = 'Your score: {}. Best score: {}'.format(self.score_1,self.highscore))
self.field.delete(self.apple)
self.create_apple()
self.create_segment()
if self.field.coords(self.segments[-1])[0] == 0 or self.field.coords(self.segments[-1])[0] == self.width or\
self.field.coords(self.segments[-1])[1] == self.height or self.field.coords(self.segments[-1])[1] == 0: # IF SNAKE'S RUN INTO WALL
self.game_over()
for x in range(2, len(self.segments)): # SELF-EATING
if self.field.coords(self.segments[0]) == self.field.coords(self.segments[x]):
self.game_over()
self.field.after(200,start)
return start()
def lets_play(self): #START
self.create_apple()
self.create_snake()
self.root.mainloop()
if __name__ == '__main__':
game = Game()
game.field.bind('<Up>', lambda x: game.change_top())
game.field.bind('<Down>', lambda x: game.change_down())
game.field.bind('<Left>', lambda x: game.change_left())
game.field.bind('<Right>', lambda x: game.change_right())
game.lets_play()