Search code examples
pythontokenturtle-graphics

I can't do that loop function


Here is my project, it' s drawing robot:

I manage to do F and R functions. But my L function always malfunctions. Here is my code:

def func(list1):
numOfElements = int(len(list1))
for i in range(numOfElements):
    if list1[i] == "L":
        list2 = list1.copy()
        for j in range(i):
            list2.pop(j)
        list2.pop(0)
        while(list1[i]!="]"):
            func(list2)
            i=i+1
    if list1[i] == "F":
        value = list1[i + 1]
        tim.forward(value)
    if list1[i] == "R":
        value = list1[i + 1]
        tim.right(value)
    else:
        pass

I am using the example in this image. My code separate them into tokens. And then i'm putting them on the list. [![enter image description here][2]][2]

I can do this if i had one L function but if there is nested L functions i can't work it out. How can i solve this problem with my L function?


Solution

  • This is a situation where you don't want a for i in range(...) loop as incrementing inside the loop, i=i+1, won't affect the value of i in the next iteration. Unlike C, the Python for loop ignores changes to the iteration variable come the next iteration.

    Also, copying tokens isn't necessary. We just need to properly keep track of where we are in the list of tokens. That includes having a recursive call return how far it got in the list of tokens before it hits a ']' and returns.

    Let's put all that together and use meaningful variable names:

    from turtle import Screen, Turtle
    
    example = ['L', 36, '[', 'L', 4, '[', 'F', 100, 'R', 90, ']', 'R', 10, ']']
    
    def func(tokens, index=0):
        while index < len(tokens):
            command = tokens[index]
            index += 1
    
            if command == 'L':
                repetitions = tokens[index]
                index += 2  # also move past '['
    
                for _ in range(repetitions):
                    new_index = func(tokens, index)
    
                index = new_index
            elif command == 'F':
                distance = tokens[index]
                index += 1
                turtle.forward(distance)
            elif command == 'R':
                angle = tokens[index]
                index += 1
                turtle.right(angle)
            elif command == ']':
                break
    
        return index
    
    screen = Screen()
    turtle = Turtle()
    
    func(example)
    
    screen.exitonclick()