如何摆脱左手算法的 while 循环

How to get rid of the while loop for my left hand algorithm

目前我正试图摆脱左手算法中的 while 循环。我想删除它的原因是因为我读了 2 stack posts and 。 @cdlane 回答了这两个问题,他删除了 while 循环并重建了一个新函数。真的很感谢这位先生,他帮助解决了我之前遇到的不少问题。我知道这背后的原因是因为 while 循环阻止代码到达 mainloop() 方法。我在 post 中看到了这个答案作为替代方案,但是我该如何修改它,因为在这种情况下,我的不是乌龟 onkey 事件,而是在我调用 class,受海龟航向影响。

这是我的算法:

from turtle import * # import the turtle library

# define the tile_size and cursor_size for usage later on
TILE_SIZE = 24 
CURSOR_SIZE = 20

class Wall(Turtle): # create Wall class to plot out the walls
    def __init__(self):
        super().__init__(shape='square') # inherit from Turtle(parent class)
        self.hideturtle() # hide the cursor
        self.shapesize(TILE_SIZE / CURSOR_SIZE) # define the size of the square
        self.pencolor('black') #  define the color that we are going to plot the grids out
        self.penup() # to prevent the pen from leaving a trace
        self.speed('fastest') # get the fastest speed

class Path(Wall): # create Path class to plot out the path
    def __init__(self):
        super().__init__() # inherit from Turtle(parent class)
        self.pencolor('white') #  define the color that we are going to plot the grids out

class Sprite(Turtle): # create Sprite class to define the turtle and its characteristics
    def __init__(self):
        super().__init__(shape='turtle') # inherit from Turtle(parent class)
        self.shapesize((TILE_SIZE / CURSOR_SIZE)-0.4) # define the size of the square
        self.color('orange') #  define the color that we are going to plot the turtle
        self.penup() # to prevent the pen from leaving a trace while shifting to the starting point
        self.goto(start_x, start_y) # move the turtle to the position
        self.speed('fastest') # set speed to slowest to observe the sprite movement


############## algorithms and manual movement here  ######################

class LeftHandAlgorithm(Sprite): # create LeftHandAlgorithm class to define how the sprite moves with LHA
    def __init__(self):
        super().__init__() # inherit from the Sprite class
        # self.hideturtle() # hide the cursor
        self.moves = 0 # create a counter to count the number of steps
        self.goto(start_x, start_y) # move the turtle to the position
        self.pendown()
        
    def spriteUp(self): # create a spriteUp function to control the turtle if it wants to move downwards
        if (self.heading() == 90): # see if sprite is facing downwards
            x_walls = round(self.xcor(), 0) # sprite x coordinates
            y_walls = round(self.ycor(), 0) # sprite y coordinates
            if (x_walls, y_walls) in finish: # check if coordinates is ald at finish point
                print('Finished Left Hand Algorithm!')
                endProgram() # exit the entire program upon clicking anywhere in the turtle window
            if ((x_walls - 24), y_walls) in walls: # check if the walls are on the left
                if (x_walls, (y_walls + 24)) not in walls: # check if the path ahead it is facing is clear
                    self.forward(24) # move forward by 1 step
                else:
                    self.right(90) # if it is blocked, turn 90 clockwise right
            else:
                self.left(90) # turn 90 deg left
                self.forward(24) # move forward by 1 step

    def spriteDown(self): # create a spriteUp function to control the turtle if it wants to move upwards
        if (self.heading() == 270): # see if sprite is facing downwards
            x_walls = round(self.xcor(), 0) # sprite x coordinates
            y_walls = round(self.ycor(), 0) # sprite y coordinates
            if (x_walls, y_walls) in finish: # check if coordinates is ald at finish point
                print('Finished Left Hand Algorithm!')
                endProgram() # exit the entire program upon clicking anywhere in the turtle window
            if ((x_walls + 24), y_walls) in walls: # check if the walls are on the left
                if (x_walls, (y_walls - 24)) not in walls: # check if the path ahead it is facing is clear
                    self.forward(24) # move forward by 1 step
                else:
                    self.right(90) # if it is blocked, turn 90 clockwise right
            else:
                self.left(90) # turn 90 deg left
                self.forward(24) # move forward by 1 step

    def spriteLeft(self): # create a spriteUp function to control the turtle if it wants to move leftwards
        if (self.heading() == 180): # see if sprite is facing downwards
            x_walls = round(self.xcor(), 0) # sprite x coordinates
            y_walls = round(self.ycor(), 0) # sprite y coordinates
            if (x_walls, y_walls) in finish: # check if coordinates is ald at finish point
                print('Finished Left Hand Algorithm!')
                endProgram() # exit the entire program upon clicking anywhere in the turtle window
            if (x_walls, (y_walls - 24)) in walls: # check if the walls are on the left
                if ((x_walls - 24), y_walls) not in walls: # check if the path ahead it is facing is clear
                    self.forward(24) # move forward by 1 step
                else:
                    self.right(90) # if it is blocked, turn 90 clockwise right
            else:
                self.left(90) # turn 90 deg left
                self.forward(24) # move forward by 1 step

    def spriteRight(self): # create a spriteUp function to control the turtle if it wants to move rightside
        if (self.heading() == 0): # see if sprite is facing downwards
            x_walls = round(self.xcor(), 0) # sprite x coordinates
            y_walls = round(self.ycor(), 0) # sprite y coordinates
            if (x_walls, y_walls) in finish: # check if coordinates is ald at finish point
                print('Finished Left Hand Algorithm!')
                endProgram() # exit the entire program upon clicking anywhere in the turtle window
            if (x_walls, (y_walls + 24)) in walls: # check if the walls are on the left
                if ((x_walls + 24), y_walls) not in walls: # check if the path ahead it is facing is clear
                    self.forward(24) # move forward by 1 step
                else:
                    self.right(90) # if it is blocked, turn 90 clockwise right
            else:
                self.left(90) # turn 90 deg left
                self.forward(24) # move forward by 1 step

def setup_maze(level): # create a setup_maze function so that we can plot out the map in turtle

    # declare maze_height and maze_width first as the limits for the entire maze
    maze_height, maze_width = len(level), len(level[0])

    # get the center point for each maze
    center_horizontal_point = (maze_width + 1) / 2
    center_vertical_point = (maze_height + 1) / 2    

    for y in range(maze_height): # for loop to limit the entire maze
        for x in range(maze_width):
            character = level[y][x] # get the character at each x,y coordinate

            # calculate the screen x, y coordinates
            screen_x = int((x - maze_width) * TILE_SIZE) + (center_horizontal_point * TILE_SIZE)
            screen_y = int((maze_height - y) * TILE_SIZE) - (center_vertical_point * TILE_SIZE)

            if character == "X":
                maze.fillcolor('grey')
                maze.goto(screen_x, screen_y)
                maze.stamp()
                walls.append((screen_x, screen_y)) # add coordinates for the wall to the list
            else:
                maze.fillcolor('white')
                maze.goto(screen_x, screen_y)
                maze.stamp()
                paths.append((screen_x, screen_y)) # add coordinates for the path to the list

            if character == "e":
                maze.fillcolor(['white', 'red'][character == 'e'])
                maze.goto(screen_x, screen_y) # proceed on to the coordinates on turtle
                maze.stamp() # stamp out the boxes
                finish.append((screen_x, screen_y)) # add coordinates for the endpoint to the list             

            if character == 's': # if statement to determine if the character is s
                maze.fillcolor('green')
                maze.goto(screen_x, screen_y)
                maze.stamp() # stamp out the boxes
                start.append((screen_x, screen_y)) # add coordinates for the startpoint to the list

def endProgram(): # exit the entire program upon clicking anywhere in the turtle window
    screen.exitonclick()

grid = []                               # create a grid list to store the labels while reading from the txt file
walls = []                              # create walls coordinate list
start = []
finish = []                             # enable the finish array
paths = []

with open("map11.txt") as file:         # open the txt file and read contents and append it to maze
    for line in file:
        grid.append(line.strip())

screen = Screen() # instantiate the Screen class from turtle
screen.setup(700, 700) # determine the size of the turtle pop out window

maze = Wall()                           # enable the Wall class
path = Path()                           # enable the Path class

setup_maze(grid)   
start_x, start_y = int((start[0])[0]), int((start[0])[1])

spriteLHA = LeftHandAlgorithm()                       # enable the Sprite class for Left Hand Algorithm

while True:
            spriteLHA.spriteUp()
            spriteLHA.spriteDown()
            spriteLHA.spriteLeft()
            spriteLHA.spriteRight()

screen.listen()
screen.mainloop()

我相信我已经按照您描述的方式修改了您的代码,将 while True 循环替换为定时事件。您可以随时单击 window 来结束程序。我将您的 UpDown 等方法更改为 return TrueFalse 以指示是否已到达完成图块,而不是结束程序他们自己。这样,这些方法的结果可用于确定是否继续计时事件:

from turtle import Screen, Turtle  # import the turtle library

# define the tile_size and cursor_size for usage later on
TILE_SIZE = 24
CURSOR_SIZE = 20

class Wall(Turtle):  # create Wall class to plot out the walls
    def __init__(self):
        super().__init__(shape='square')  # inherit from Turtle(parent class)
        self.hideturtle()  # hide the cursor
        self.shapesize(TILE_SIZE / CURSOR_SIZE)  # define the size of the square
        self.pencolor('black')  # define the color that we are going to plot the grids out
        self.penup()  # to prevent the pen from leaving a trace
        self.speed('fastest')  # get the fastest speed

class Path(Wall):  # create Path class to plot out the path
    def __init__(self):
        super().__init__()  # inherit from Turtle(parent class)
        self.pencolor('white')  # define the color that we are going to plot the grids out

class Sprite(Turtle):  # create Sprite class to define the turtle and its characteristics
    def __init__(self):
        super().__init__(shape='turtle')  # inherit from Turtle(parent class)
        self.shapesize((TILE_SIZE / CURSOR_SIZE)-0.4)  # define the size of the square
        self.color('orange')  # define the color that we are going to plot the turtle
        self.penup()  # to prevent the pen from leaving a trace while shifting to the starting point
        self.goto(start_x, start_y)  # move the turtle to the position
        self.speed('fastest')  # set speed to slowest to observe the sprite movement

############## algorithms and manual movement here  ######################

class LeftHandAlgorithm(Sprite):  # create LeftHandAlgorithm class to define how the sprite moves with LHA
    def __init__(self):
        super().__init__()  # inherit from the Sprite class
        # self.hideturtle()  # hide the cursor
        self.moves = 0  # create a counter to count the number of steps
        self.goto(start_x, start_y)  # move the turtle to the position
        self.pendown()

    def spriteUp(self):  # create a spriteUp function to control the turtle if it wants to move downwards
        if self.heading() == 90:
            x_walls = round(self.xcor(), 0)  # sprite x coordinates
            y_walls = round(self.ycor(), 0)  # sprite y coordinates
            if (x_walls, y_walls) in finish:  # check if coordinates is at finish point
                print("Finished Left Hand Algorithm!")
                return False

            if ((x_walls - 24), y_walls) in walls:  # check if the walls are on the left
                if (x_walls, (y_walls + 24)) not in walls:  # check if the path ahead it is facing is clear
                    self.forward(24)  # move forward by 1 step
                else:
                    self.right(90)  # if it is blocked, turn 90 clockwise right
            else:
                self.left(90)  # turn 90 deg left
                self.forward(24)  # move forward by 1 step

        return True

    def spriteDown(self):  # create a spriteUp function to control the turtle if it wants to move upwards
        if self.heading() == 270:
            x_walls = round(self.xcor(), 0)  # sprite x coordinates
            y_walls = round(self.ycor(), 0)  # sprite y coordinates
            if (x_walls, y_walls) in finish:  # check if coordinates is at finish point
                print("Finished Left Hand Algorithm!")
                return False

            if ((x_walls + 24), y_walls) in walls:  # check if the walls are on the left
                if (x_walls, (y_walls - 24)) not in walls:  # check if the path ahead it is facing is clear
                    self.forward(24)  # move forward by 1 step
                else:
                    self.right(90)  # if it is blocked, turn 90 clockwise right
            else:
                self.left(90)  # turn 90 deg left
                self.forward(24)  # move forward by 1 step

        return True

    def spriteLeft(self):  # create a spriteUp function to control the turtle if it wants to move leftwards
        if self.heading() == 180:
            x_walls = round(self.xcor(), 0)  # sprite x coordinates
            y_walls = round(self.ycor(), 0)  # sprite y coordinates
            if (x_walls, y_walls) in finish:  # check if coordinates is at finish point
                print("Finished Left Hand Algorithm!")
                return False

            if (x_walls, (y_walls - 24)) in walls:  # check if the walls are on the left
                if ((x_walls - 24), y_walls) not in walls:  # check if the path ahead it is facing is clear
                    self.forward(24)  # move forward by 1 step
                else:
                    self.right(90)  # if it is blocked, turn 90 clockwise right
            else:
                self.left(90)  # turn 90 deg left
                self.forward(24)  # move forward by 1 step

        return True

    def spriteRight(self):  # create a spriteUp function to control the turtle if it wants to move rightside
        if self.heading() == 0:
            x_walls = round(self.xcor(), 0)  # sprite x coordinates
            y_walls = round(self.ycor(), 0)  # sprite y coordinates
            if (x_walls, y_walls) in finish:  # check if coordinates is at finish point
                print("Finished Left Hand Algorithm!")
                return False

            if (x_walls, (y_walls + 24)) in walls:  # check if the walls are on the left
                if ((x_walls + 24), y_walls) not in walls:  # check if the path ahead it is facing is clear
                    self.forward(24)  # move forward by 1 step
                else:
                    self.right(90)  # if it is blocked, turn 90 clockwise right
            else:
                self.left(90)  # turn 90 deg left
                self.forward(24)  # move forward by 1 step

        return True

def setup_maze(level):  # create a setup_maze function so that we can plot out the map in turtle

    # declare maze_height and maze_width first as the limits for the entire maze
    maze_height, maze_width = len(level), len(level[0])

    # get the center point for each maze
    center_horizontal_point = (maze_width + 1) / 2
    center_vertical_point = (maze_height + 1) / 2

    for y in range(maze_height):  # for loop to limit the entire maze
        for x in range(maze_width):
            character = level[y][x]  # get the character at each x,y coordinate

            # calculate the screen x, y coordinates
            screen_x = int((x - maze_width) * TILE_SIZE) + (center_horizontal_point * TILE_SIZE)
            screen_y = int((maze_height - y) * TILE_SIZE) - (center_vertical_point * TILE_SIZE)

            if character == 'X':
                maze.fillcolor('grey')
                maze.goto(screen_x, screen_y)
                maze.stamp()
                walls.append((screen_x, screen_y))  # add coordinates for the wall to the list
            else:
                maze.fillcolor('white')
                maze.goto(screen_x, screen_y)
                maze.stamp()
                paths.append((screen_x, screen_y))  # add coordinates for the path to the list

            if character == 'e':
                maze.fillcolor(['white', 'red'][character == 'e'])
                maze.goto(screen_x, screen_y)  # proceed on to the coordinates on turtle
                maze.stamp()  # stamp out the boxes
                finish.append((screen_x, screen_y))  # add coordinates for the endpoint to the list

            if character == 's':  # if statement to determine if the character is s
                maze.fillcolor('green')
                maze.goto(screen_x, screen_y)
                maze.stamp()  # stamp out the boxes
                start.append((screen_x, screen_y))  # add coordinates for the startpoint to the list

grid = []  # create a grid list to store the labels while reading from the txt file
walls = []  # create walls coordinate list
start = []
finish = []
paths = []

with open("map11.txt") as file:  # open the txt file and read contents and append it to maze
    for line in file:
        grid.append(line.strip())

screen = Screen()  # instantiate the Screen class from turtle
screen.setup(700, 700)  # determine the size of the turtle pop out window

maze = Wall()
path = Path()

setup_maze(grid)
start_x, start_y = int((start[0])[0]), int((start[0])[1])

spriteLHA = LeftHandAlgorithm()  # enable the Sprite class for Left Hand Algorithm

def run():
    if spriteLHA.spriteUp() and spriteLHA.spriteDown() and spriteLHA.spriteLeft() and spriteLHA.spriteRight():
        screen.ontimer(run)

run()

screen.exitonclick()  # exit the entire program upon clicking anywhere in the turtle window