pythonlinked-listturtle-graphicspython-turtle

Turtle snake chain project


Below is a Python code for my "Snake Project" (with Turtle and Tkinter).

The purpose of this program is to create a chain of turtles, called followers, that follow each other, with the first turtle in the chain following a special turtle: the leader. The leader itself follows the movement of the mouse.

It removes the last follower from the chain when the "Del" key is pressed.

Since it is not possible to physically delete Followers from memory, when the last Follower in the chain is removed, it is added in the first position of another chain that contains all the "deleted" Followers.
When a new Follower needs to be added to the chain, we first check if there are any in the deleted list and reuse one if available; otherwise, a new one must be created.

However, with my Python code, only the last Turtle is deleted when I click on the "Del" key, even if I press it several times. (Normally, it should delete each time the last follower).

I think the problem has to do with the method:

remove_last_follower(self, event)

of the "Leader" class.

Do you have any idea how to resolve this problem? Thanks a lot for you support.

My Python code:

from  turtle import Turtle, Screen, window_width, window_height # Importation du module Turtle

D = 30 # Distance entre les tortues

screen = Screen()

class Follower(Turtle):
    def __init__(self, name):
        Turtle.__init__(self)
        self.shape("circle")
        self.color("lightblue")
        self.penup()
        self.Prev = None
        self.Next = None
        self.Name = "T" + str(name)  
        self.coucou = False
   
   
    def move(self, x, y):    
        angle = self.towards(x, y)
        self.setheading(angle)
        self.setposition(x,y)
        self.back(20)
        if self.Next:
            x, y = self.pos()
            self.Next.move(x,y)
       

class Leader(Follower): 
    def __init__(self):
        super().__init__('tkz')
        self.shape("turtle")
        self.color("lightgreen")
        self.Last = None
        self.is_moving = False
        self.freeze = False
        self.deleted_followers = [] 
   
    def freeeze(self, event): 
        self.freeze = not self.freeze
   
   
    def add_follower(self, name):
        if self.deleted_followers:
            new_follower = self.deleted_followers.pop()
            new_follower.showturtle()
            new_follower.goto(new_follower.Prev.pos())
            new_follower.setheading(new_follower.Prev.heading())
        else:
            new_follower = Follower(name)
    
        if self.Last == None:
            self.Last = new_follower
            self.Next = new_follower
            new_follower.Prev = self
        else:
            self.Last.Next = new_follower
            self.Last = new_follower
            new_follower.Prev = self.Last
    
        new_follower.Next = None
       
       
    def move(self, event):
        if self.freeze == False:
            x, y = event.x - window_width()/2, -event.y + window_height()/2
            angle = self.towards(x, y) 
            self.setheading(angle)
            self.goto(x, y)
            #self.forward(-20)
            if self.Next:
                self.Next.move(x, y)
    

   
    def on_move(self, event):
        if self.is_moving:
            return
        self.is_moving = True
        self.move(event)
        self.is_moving = False
   
    
    def remove_last_follower(self, event):
        if self.Last:
            last_follower = self.Last
        if last_follower.Prev:
            self.Last = last_follower.Prev
            self.Last.Next = None
        else:
            self.Last = None
            self.Next = None
        last_follower.hideturtle() 
        self.deleted_followers.append(last_follower)
    screen.delay(0)



try:
    le = Leader()
except:
    le = Leader()

   


screen.cv.bind("<Button-1>", le.add_follower)
screen.cv.bind("<Button-3>", le.freeeze)
screen.cv.bind("<Delete>", le.remove_last_follower)

screen.cv.bind("<Motion>", le.on_move)
screen.listen()
screen.mainloop()    

Solution

  • The linked list in add_follower isn't updated correctly.

    Change:

    self.Last.Next = new_follower
    self.Last = new_follower          # self.Last updated
    new_follower.Prev = self.Last     # should be the *old* version of self.Last
    

    To:

    self.Last.Next = new_follower
    temp = self.Last                 # save previous Last
    self.Last = new_follower         # assign new Last
    new_follower.Prev = temp         # assign previous correctly
    

    Or even:

    self.Last.Next = new_follower
    self.Last, new_follower.Prev = new_follower, self.Last