← Teacher guide

A map of rooms

Students store a map in dictionaries (rooms by name, and each room's exits), look values up by key, check keys with in, use a dictionary inside a dictionary, and count words with a dictionary.

Deeper Python in the console · Lists and dictionaries · about 50 minutes · Open the student lesson

Classroom resources

Load these into Waypoints Prepare: choose Load URL and paste the copied address, or download the file and import it. In Prepare, the worksheet's Teacher edition shows the answers; the student copy hides them.

Students will be able to

Timing

Predict and Run 10 min · Investigate 15 min · Modify 10 min · Make 15 min

Before class

Read the unit primer first. A dictionary pairs keys with values: {"north": "kitchen"}; exits["north"] looks up the value. Keys must match exactly (the bug task: "Hall" is not "hall", so KeyError). "west" in exits checks for a key. exits[here] is itself a dictionary, so exits[here]["north"] looks up twice. ", ".join(exits[here]) joins the keys. Counting with a dictionary (the Make task) is a classic pattern: a new key starts at 1, an existing one goes up by 1.

Running the lesson

  1. Predict: draw the dictionary as a two-column table, key and value.
  2. Run: draw the map (hall in the middle, kitchen north, garden east) and walk it with the class.
  3. Investigate: read exits["hall"]["east"] in two steps: the hall's exits, then east.
  4. Bug task: ask what Hall and hall have in common, and what Python thinks.
  5. Make: act it out with words on cards. A new word gets a tally of 1; a word seen before gets another tally.

The hard part (on purpose)

A dictionary of dictionaries: two lookups in one line. Have them say each step aloud (which room, then which way) before writing rooms[here][way].

When students get stuck

What you will seeA question to askThe fix
KeyError: ...Is the key spelled exactly as it was stored, capitals included?Tidy text before using it as a key (lower()), or check with in first.
The new room cannot be reached.Which room's exits lead to it?Add it to another room's exits as well as to rooms and exits.
The word counter crashes on the first word (KeyError).What is counts[word] before that word has been seen?If the word is not in counts yet, set it to 1; otherwise add 1.

Answers to the checks

  1. Predict: What is the first line it prints?
    kitchen: the value stored under the key "north". The second line is False, because "west" is not a key.
  2. A dictionary in a dictionary: What is exits["hall"]["east"]?
    "garden"
    exits["hall"] is the hall's own exits dictionary; ["east"] looks up east in it: the garden.
  3. A wall: You are in the kitchen and type go west. What happens?
    It prints You can't go that way.
    "west" in exits["kitchen"] is False (the kitchen only has south), so the else replies instead of looking it up.
  4. Spot the bug: This stops with KeyError: Hall. Click the line that causes it.
    line 2
    Keys must match exactly: the room is "hall", but here is "Hall" with a capital. Dictionaries do not guess.
  5. Where this leads: A game stores each player's score by name: scores["Ada"] = 12. What is scores?
    A dictionary
    Looking things up by name is what dictionaries are for: scores, contacts, translations, maps.

Solutions

One possible solution for each task. Other correct programs are fine.

Modify › An attic

rooms = {
    "hall": "A long hall with a creaky floor.",
    "kitchen": "A kitchen that smells of toast.",
    "garden": "A garden full of tall grass.",
    "attic": "A dusty attic full of old boxes.",
}
exits = {
    "hall": {"north": "kitchen", "east": "garden", "up": "attic"},
    "kitchen": {"south": "hall"},
    "garden": {"west": "hall"},
    "attic": {"down": "hall"},
}
here = "hall"
while True:
    print(rooms[here])
    print("Exits: " + ", ".join(exits[here]))
    command = input("> ").strip().lower()
    words = command.split()
    if command == "quit":
        break
    elif len(words) == 2 and words[0] == "go":
        if words[1] in exits[here]:
            here = exits[here][words[1]]
        else:
            print("You can't go that way.")
    else:
        print("Try: go north, or quit")

Modify › Count the moves

rooms = {
    "hall": "A long hall with a creaky floor.",
    "kitchen": "A kitchen that smells of toast.",
    "garden": "A garden full of tall grass.",
}
exits = {
    "hall": {"north": "kitchen", "east": "garden"},
    "kitchen": {"south": "hall"},
    "garden": {"west": "hall"},
}
here = "hall"
moves = 0
while True:
    print(rooms[here])
    print("Exits: " + ", ".join(exits[here]))
    command = input("> ").strip().lower()
    words = command.split()
    if command == "quit":
        print("You made " + str(moves) + " moves.")
        break
    elif len(words) == 2 and words[0] == "go":
        if words[1] in exits[here]:
            here = exits[here][words[1]]
            moves += 1
        else:
            print("You can't go that way.")
    else:
        print("Try: go north, or quit")

Make a word counter

sentence = input("Type a sentence: ").strip().lower()
counts = {}
for word in sentence.split():
    if word in counts:
        counts[word] += 1
    else:
        counts[word] = 1
for word in counts:
    print(word + ": " + str(counts[word]))

Stretch and support

Stretch: Put things in rooms (a dictionary from room to a list of things) and let the player take them into last lesson's bag.

Support: Give students the loop over the words and the if, and ask them to fill in the two lines that count.

Exit ticket

ages = {"Ada": 12}. What do ages["Ada"] and "Bo" in ages give?

12, and False: Bo is not a key.

What each step is for

Where it leads

This completes the lessons that run in the turtle playground. Still to come: errors with try, saving the game to a file, and the text adventure, which joins the parser, the bag and the map. Data detective uses lists of dictionaries for real data.