3. Lists and Turtle Drawing

Quick Overview of Day

Use lists while moving turtles.

3.1. Check Your Understanding

    lists-and-turtles1: What will be the result of the following code being executed?

    import turtle
    
    def draw_thing(some_turtle, tasks):
        for value in tasks:
            some_turtle.forward(value)
            some_turtle.stamp()
            some_turtle.backward(value)
            some_turtle.right(30)
    
    window = turtle.Screen()
    bob = turtle.Turtle()
    
    my_list = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120]
    draw_thing(bob, my_list)
    
    ../../_images/turtle-list-options.png
  • Option 1
  • Nice!
  • Option 2
  • Try again.
  • Option 3
  • Try again.
  • Error, will not run.
  • Try again.

    lists-and-turtles2: What will be the result of the following code being executed?

    import turtle
    
    def draw_thing(some_turtle, tasks):
        for value in tasks:
            some_turtle.forward(value)
            some_turtle.stamp()
            some_turtle.right(30)
    
    window = turtle.Screen()
    bob = turtle.Turtle()
    
    my_list = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120]
    draw_thing(bob, my_list)
    
    ../../_images/turtle-list-options.png
  • Option 1
  • Try again.
  • Option 2
  • Nice!
  • Option 3
  • Try again.
  • Error, will not run.
  • Try again.

3.2. Turtle Coordinate List

Recall that you can use in to check for membership in a list as follows:

If a portion of your list is itself a list, you need to check for the entire sublist when using in.

If we wanted to keep track of a collection of coordinates (x and y pairs), we could do it by creating a list that contains sublists of coordinates. In the list below, three ordered pairs of coordinates are given:

coordinates = [[0, 0], [10, 20], [150, 80]]
  1. x: 0, y: 0
  2. x: 10, y: 20
  3. x: 150, y: 80

To check if a specific x and y pair is in our coordinate list, we can use in as follows:

Note

Change the numbers in the if statement above to an ordered pair that is in the list, then run the code again.

Imagine that you wanted to create a simulation of a turtle walking around a grid world (in other words, the turtle would always turn by 90 degrees). Before each “step” the turtle takes, we will randomly choose to either turn left and move, turn right and move, or move straight ahead. Although we could move any amount for each “step”, let’s use a step size of 10. The following program implements this world, but is in an infinite loop. The program should automatically time out after running for 20 seconds in the browser (though if you are executing it in Thonny, you will need to press the Stop button).

Instead of having this program run forever, we would like the turtle to automatically stop the program whenever it walks onto a location that it has been before. In order to do that, we need to keep a list of coordinates that the turtle has been. Since the turtle begins at the origin, we will add [0, 0] to the list before any movement occurs. Since the turtle module keeps track of the turtle location using floating point values, the program will not behave the way you want if you simply store the current x and y positions in the coordinate list. Instead, we will convert the x and y values to be the nearest integer value, and store those in the list.

After every step that the turtle takes, we need to get the current x and y coordinates, in the form of [x, y]. If this ordered pair appears in the coordinate list, it means that we have been here before and we should end the program. If not, we need to add this ordered pair to the coordinate list and continue moving. The program below implements this behaviour.

3.3. The Return of L-Systems

Let’s return to the L-systems we introduced previously and introduce a very interesting new feature that requires the use of lists.

Suppose our L-System has the following rules:

X --> F[-X]+X
F --> FF

This L-system looks very similar to the old L-system, except that we’ve added the characters [ and ]. The meaning of these characters adds a very interesting new dimension to our L-Systems. The [ character indicates that we want to save the state of our turtle, namely its position and its heading (direction the turtle is facing) so that we can come back to this position later. The ] tells the turtle to warp to the most recently saved position. The way that we will accomplish this is to use lists. We can save the heading and position of the turtle as a list of 3 elements, like this: [heading, x, y]. The index position 0 in the list holds the heading, index position 1 in the list holds the x coordinate, and index position 2 holds the y coordinate.

Now, if we create an empty list and every time we see a [ we append a list that contains [heading, x, y], we create a history of saved places the turtle has been where the most recently saved location will always be at the end of the list. When we find a ] in the string we use the pop function to remove the the most recently appended information.

Let’s modify our draw_l_system function to begin to implement this new behavior.

When we run this example we can see that the picture is not very interesting, but notice what gets printed out, and how the saved information about the turtle gets added and removed from the end of the list. In the next example we’ll make use of the information from the list to save and restore the turtle’s position and heading when needed. We’ll use a longer example here so you get an idea of what the kind of drawing the L-System can really make.

3.4. Putting It All Together

To determine the instruction_string we used in the last example, we used an axiom of X and applied the following rules 6 times:

X --> F[-X]+X
F --> FF

If you run the code below, you will not see much happen. To fix the code below, you need to:

  • fix the apply_rules function so that the rules given above are applied
  • fix the call to create_l_system to use the correct axiom and number_of_iterations

Note

Once you have the code working, try it out with a larger number of iterations. You may also want to try this example with different values for the angle and distance parameters.

3.5. Practice Problems

3.5.1. Garden Herb

Here are the rules for an L-system that creates something that resembles a common garden herb. Use an angle of 27.5 degrees, and a distance of 5.

Axiom: H
Rule 1: H --> HFX[+H][-H]
Rule 2: X --> X[-FFF][+FFF]FX

If you iterated through the rules 5 times to create your instruction_string, and used a distance of 5, your code should have created something that looks like the following:

../../_images/garden-herb.png

3.5.2. Branch

Here are the rules for an L-system that creates something that resembles a branch. Use an angle of 25 degrees, and a distance of 5.

Axiom: F
Rule 1: F --> F[-F]F[+F]F

If you iterated through the rules 4 times to create your instruction_string, and used a distance of 5, your code should have created something that looks like the following:

../../_images/branch.png

3.5.3. Symmetrical Branch

Here are the rules for an L-system that creates something that resembles a symmetrical branch. Use an angle of 25.7 degrees, and a distance of 5.

Axiom: X
Rule 1: X --> F[+X][-X]FX
Rule 2: F --> FF

If you iterated through the rules 5 times to create your instruction_string, and used a distance of 5, your code should have created something that looks like the following:

../../_images/symmetrical-branch.png

3.5.4. Seaweed

Here are the rules for an L-system that creates something that resembles seaweed. Use an angle of 22.5 degrees, and a distance of 10.

Axiom: F
Rule 1: F --> FF-[-F+F+F]+[+F-F-F]

If you iterated through the rules 4 times to create your instruction_string, and used a distance of 10, your code should have created something that looks like the following:

../../_images/seaweed.png

3.5.5. Create Your Own

Experiment by creating your own rules for an L-system. Be sure to use the [ and ] characters in the rule(s) of your L-system.

Next Section - Project Overview