Написал тривиальную змейку на 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()