← Objects with turtles

Lists of stars

Keep the stars in a list and their speeds and points in lists beside it, so one loop moves them all, and find out why lists side by side are fragile.

A game with a hundred enemies does not have a hundred variables. It keeps them in a list and loops over it.

Last lesson every star cost 11 lines. This version keeps the stars in a list, and what each star needs to remember (its speed, its points) in more lists beside it. Place i in every list is about the same star.

PredictRead the code and say what it will do before you run anything. A wrong guess is fine: it shows you what to look for.

Predict

stars.py
speeds = [3, 8, 5, 6]
points = [1, 1, 5, 1]
print(speeds[2], points[2])

speeds and points have one item per star. speeds[2] and points[2] are both about the third star. What will it print?

What does it print?

RunRun it and compare the result with your prediction.

Run

The same game, now with four stars made by a loop. Play it (click the picture, then use the arrow keys). stars.append(s) adds each new star to the end of the list.

stars.py
from turtle import *
import random

speed(0)
penup()
goto(0, -180)
left(90)
score = 0

pen = Turtle()
pen.hideturtle()
pen.penup()
pen.goto(-220, 200)

stars = []
speeds = []
points = []
for i in range(4):
    s = Turtle()
    s.shape("circle")
    s.color("gold")
    s.penup()
    s.goto(-150 + i * 100, 200)
    s.setheading(270)
    stars.append(s)
    speeds.append(random.randint(3, 7))
    points.append(1)

def show_score():
    pen.clear()
    pen.write("Score: " + str(score), False, "left", ("Arial", 16, "normal"))

def go_left():
    goto(xcor() - 25, ycor())

def go_right():
    goto(xcor() + 25, ycor())

def tick():
    global score
    for i in range(len(stars)):
        stars[i].forward(speeds[i])
        if stars[i].distance(xcor(), ycor()) < 25:
            score += points[i]
            stars[i].goto(random.randint(-200, 200), 200)
        if stars[i].ycor() < -220:
            stars[i].goto(random.randint(-200, 200), 200)
    show_score()
    ontimer(tick, 50)

onkey(go_left, "Left")
onkey(go_right, "Right")
listen()
show_score()
tick()
mainloop()
Try it yourselfYour edits are saved in this browser.

InvestigateTrace how each line of code connects to what you see.

Investigate

stars.py
from turtle import *
import random

speed(0)
penup()
goto(0, -180)
left(90)
score = 0

pen = Turtle()
pen.hideturtle()
pen.penup()
pen.goto(-220, 200)

stars = []
speeds = []
points = []
for i in range(4):
    s = Turtle()
    s.shape("circle")
    s.color("gold")
    s.penup()
    s.goto(-150 + i * 100, 200)
    s.setheading(270)
    stars.append(s)
    speeds.append(random.randint(3, 7))
    points.append(1)

def show_score():
    pen.clear()
    pen.write("Score: " + str(score), False, "left", ("Arial", 16, "normal"))

def go_left():
    goto(xcor() - 25, ycor())

def go_right():
    goto(xcor() + 25, ycor())

def tick():
    global score
    for i in range(len(stars)):
        stars[i].forward(speeds[i])
        if stars[i].distance(xcor(), ycor()) < 25:
            score += points[i]
            stars[i].goto(random.randint(-200, 200), 200)
        if stars[i].ycor() < -220:
            stars[i].goto(random.randint(-200, 200), 200)
    show_score()
    ontimer(tick, 50)

onkey(go_left, "Left")
onkey(go_right, "Right")
listen()
show_score()
tick()
mainloop()

What changes for more stars?

Follow i through the lists.

Lists that fell out of step.

What would you change to play with eight stars?

speeds is [4, 7, 3, 5] and points is [1, 1, 1, 1]. Fill in what the loop in tick uses for each star.

iwhich starspeeds[i]points[i]
01st41
12nd
34th

Someone made a fifth star but it stops with an IndexError. Click the line where Python stops.

ModifyChange the code on purpose and check the result.

Modify

Play with six stars.

Need a hint?

The number of stars is set in one place: the range in the loop that makes them.

Make each star worth a random 1 to 3 points.

Need a hint?

points.append(1) gives every star 1 point. Use random.randint(1, 3) instead.

Try it yourselfYour edits are saved in this browser.

Play with six stars.

    Run your program. This ticks when your code does all of the above.

    Give each star a random 1 to 3 points.

      Run your program. This ticks when your code does all of the above.

      MakeBuild something new using what you have learned. Expect a few tries; that is normal.

      Make a bad star

      Make the first star a bad star: add a fourth list, bad, with True for the first star and False for the others. Colour the bad star red. Catching it costs 3 points; catching any other star adds its points.

      Try it yourselfYour edits are saved in this browser.

      Add a list called bad: the first star is red and costs 3 points when caught.

        Run your program. This ticks when your code does all of the above.

        Info

        Where this leads

        Lists made the number of stars one number. But everything about one star is now spread over four lists. Next lesson keeps it together.

        Each star now has a turtle, a speed, points and bad in four lists. What happens if one list gets a star the others do not?

        For teachers

        Students rebuild the stars game with a list of stars and lists of speeds and points beside it, so one loop moves every star, then meet the weakness of lists side by side (they must stay in step). About 50 minutes.

        Open the teacher guide: answers, solutions, slides and a worksheet.

        Students will be able to

        Before class

        Read the unit primer first. stars.append(s) adds a turtle to the end of a list. speeds[i] and points[i] are the values for stars[i]: lists side by side ("parallel lists") linked only by the place number. They work while every list is changed together, and break when one is not. The bug task shows this: five stars but four speeds gives IndexError: list index out of range. The lesson ends with four lists for one star, which is the problem next lesson fixes.

        Running the lesson

        1. Predict: places start at 0, so place 2 is the third item. Point at the same column in both lists.
        2. Run: ask how many lines a fifth star costs now (one number) compared with last lesson (11 lines).
        3. Investigate: in the trace, say each row aloud: star 1 uses speed 7 and 1 point.
        4. Bug task: ask students to count the stars and the speeds. Then ask which line should change.
        5. Make: four lists for one star. Ask what could go wrong when someone adds a fifth property.

        The hard part (on purpose)

        Keeping lists side by side in step. Let the IndexError happen, then ask them to count the items in each list.

        When students get stuck

        Stretch and support

        Stretch: Add a fifth list, sizes, and use it to make some stars bigger with turtlesize-style shapes (or different shapes) and worth more.

        Support: Give students the bad list already filled in, and ask them only to change what happens when a star is caught.

        Where it leads

        Next lesson keeps everything about one star in one dictionary, so nothing can fall out of step. Databases have the same choice: separate columns kept in step, or one record per thing.

        What each step is for

        Now you can
        Next lesson3. One dictionary per starKeep everything about one star together in a dictionary, so adding a property is one line and nothing can fall out of step.