Learn to use dictionaries for complex data, read and write files, and use Python modules.
Think of a game where you have a collection of creatures. Each creature has a name, a type, hit points, and attack power. How would you store all this information about a single creature? You could use separate variables, but that gets messy fast. This is where dictionaries come in, a perfect structure for grouping multiple pieces of information under one roof.
And what if you want to save your game progress so you can continue tomorrow? Just like a save slot in a video game, Python lets you write data to a file and read it back later. In this lesson you will learn to work with dictionaries, files, and modules, three tools that will open up a whole new world of possibilities.
The final battle is near. In this lesson you build the enemy database of the Python Kingdom using dictionaries, implement a save/load system with files, and add random encounters using the random module. By the end, you will have a complete RPG game with all systems working together!
A dictionary in Python is a collection of key-value pairs. Think of it like a creature's stat card: on the left you have the label (name, type, HP) and on the right you have the corresponding value.
You create a dictionary using curly braces {}:
Result:
{'name': 'Flamarion', 'type': 'fire', 'hp': 95, 'attack': 28}Each element in the dictionary has two parts separated by :, the key (on the left) and the value (on the right). Keys are usually strings, and values can be anything: strings, numbers, lists, even other dictionaries.
You can also create an empty dictionary and add elements as you go:
Result:
{'name': 'Aquadon', 'type': 'water', 'hp': 110, 'attack': 22}To get a value from a dictionary, you use the key inside square brackets:
Result:
Creature name: Flamarion
Hit points: 95If you try to access a key that does not exist, you get a KeyError. To avoid that, you can use the get() method, which returns None (or a default value) if the key is missing:
Result:
Speed: 0You can modify values the same way you set them initially:
Result:
HP before battle: 95
HP after battle: 65
Attack after evolution: 42When you want to display all the information about a creature, you use a for loop. The items() method gives you access to each key-value pair:
Result:
=== Creature Stat Card ===
name : Terravolt
type : earth
hp : 130
attack : 35You can also iterate over just the keys or just the values:
Result:
name
type
hp
attack
---
Terravolt
earth
130
35You can check if a key exists in a dictionary with the in operator:
Result:
The creature has 130 hit points.
We do not know this creature's speed.Imagine you have two separate lists: one with creature names and one with their types. The zip() function combines them into pairs, like a zipper joining two sides:
Result:
[('Flamarion', 'fire'), ('Aquadon', 'water'), ('Terravolt', 'earth')]Super useful: you can directly transform the result of zip() into a dictionary with dict():
Result:
{'Flamarion': 'fire', 'Aquadon': 'water', 'Terravolt': 'earth'}In a single line you created a complete dictionary. That is the power of zip().
The split() method takes a string and cuts it into pieces, returning a list. By default, it splits on spaces:
Result:
['Flamarion', 'fire', '95', '28']You can also specify a different separator. For example, if the data is separated by commas:
Result:
['Aquadon', 'water', '110', '22']
{'name': 'Aquadon', 'type': 'water', 'hp': 110, 'attack': 22}Notice that we used int() for HP and attack, because split() always returns strings, even if they look like numbers.
The sorted() function returns a sorted version of a list, without modifying the original list:
Result:
Original: [12, 5, 23, 8, 17, 3]
Sorted: [3, 5, 8, 12, 17, 23]
Descending: [23, 17, 12, 8, 5, 3]It also works with strings, sorting them in alphabetical order:
Result:
Alphabetical order: ['Aquadon', 'Breezel', 'Flamarion', 'Terravolt']You can also sort the keys of a dictionary:
Result:
Creatures sorted by name:
Aquadon: 110 HP
Flamarion: 95 HP
Terravolt: 130 HPYou have two main ways to delete elements from a dictionary.
del removes a key completely:
Result:
Before: {'name': 'Flamarion', 'type': 'fire', 'hp': 95, 'attack': 28}
After del: {'name': 'Flamarion', 'hp': 95, 'attack': 28}pop() removes the key and returns the deleted value. Useful if you need it:
Result:
Saved HP: 110
Remaining dictionary: {'name': 'Aquadon', 'type': 'water', 'attack': 22}With pop() you can also specify a default value, so you do not get an error if the key does not exist:
Result:
Ability: noneNow comes the interesting part: saving data to a file. Think of it like a save game. You write data to disk so you can find it again tomorrow.
To write to a file, you use open() with the "w" (write) mode:
A few important things:
"w" means "write". If the file already exists, the old content is erased"a" (append) adds to the end without erasing what was there before"\n" creates a new line in the filestr(value) converts numbers to text, because write() only accepts stringsfile.close(), otherwise data might be lostTo load data back, you open the file with the "r" (read) mode:
Result:
=== Save Game ===
name: Flamarion
type: fire
hp: 95
attack: 28If you want to read line by line, use readlines():
This is useful when you want to process each line separately, for example to reconstruct a dictionary from saved data:
Result:
Loaded creature: {'name': 'Flamarion', 'type': 'fire', 'hp': '95', 'attack': '28'}In the examples above, you had to remember to call close() after each open(). If you forget, problems can arise. Data might not be fully saved or the file might remain locked.
Python offers a more elegant solution: with open(). This syntax automatically closes the file when the code block ends, even if an error occurs:
Result:
Saved successfully!
name: Breezel
type: wind
hp: 80
attack: 24Always use with open() instead of plain open(). It is safer, cleaner, and you do not have to worry about forgetting to close the file.
Modules are like extensions that you load into your program. Python comes with dozens of built-in modules, and two of the most useful ones are random and os.
random lets you generate random values, perfect for game mechanics:
Each run will produce different results, and that is exactly the point. The main functions are:
random.randint(a, b) - random integer between a and b (inclusive)random.choice(list) - picks a random element from a listrandom.shuffle(list) - shuffles the elements of a list (modifies the list directly)os gives you access to operating system functions. You can check if a file exists, create folders, or list the contents of a directory:
The os module is especially useful when working with files and you want to make sure everything exists before you try to read or write.
You can also import specific functions with from ... import:
Dictionaries store data in key-value pairs, perfect for structured information like a creature's stats. Files let you save and load data, just like a save game. Always use with open() for safety, and the random and os modules extend what your programs can do.
Create a dictionary for a monster called "Goblin" with the keys: "name", "hp", "attack", and "gold_reward". Then create a second dictionary for "Dark Bug" (the final boss) with higher stats. Display both enemies' stat cards using a for loop with .items().
SET goblin = {"name": "Goblin", "hp": 40, "attack": 8, "gold_reward": 15}
SET dark_bug = {"name": "Dark Bug", "hp": 200, "attack": 25, "gold_reward": 100}
DISPLAY "=== Enemy Database ==="
FOR key, value IN goblin.items():
DISPLAY key + ": " + value
DISPLAY empty line
FOR key, value IN dark_bug.items():
DISPLAY key + ": " + valueWrite a program that saves the hero's data to a file called "hero_save.txt". The hero has: name="Aldric", hero_class="Warrior", hp=95, attack=25, defense=15, gold=120. Write each stat on a separate line in the format "key:value". Use with open() for safety.
SET hero = {"name": "Aldric", "class": "Warrior", "hp": 95, "attack": 25, "defense": 15, "gold": 120}
WITH open("hero_save.txt", "w") AS file:
FOR key, value IN hero.items():
file.write(key + ":" + str(value) + newline)
DISPLAY "Hero saved!"Write a program that loads the hero's data from "hero_save.txt" (created in the previous exercise). Read the file, split each line by ":", and reconstruct the hero dictionary. Use os.path.exists() to check if the file exists before loading. Display the loaded hero stats.
IMPORT os
IF os.path.exists("hero_save.txt"):
SET hero = {}
WITH open("hero_save.txt", "r") AS file:
FOR line IN file.readlines():
line = line.strip()
IF ":" IN line:
SET parts = line.split(":")
hero[parts[0]] = parts[1]
DISPLAY "Hero loaded!"
DISPLAY hero
ELSE:
DISPLAY "No save found!"Create a list of 4 enemy dictionaries (each with "name", "hp", "attack"). Use random.choice() to pick a random enemy. Display which enemy appeared and simulate a simple battle where the hero (attack=20) attacks until the enemy's HP reaches 0. Count the rounds and display the result.
IMPORT random
SET enemies = [
{"name": "Goblin", "hp": 30, "attack": 8},
{"name": "Skeleton", "hp": 40, "attack": 10},
{"name": "Orc", "hp": 50, "attack": 12},
{"name": "Ghost", "hp": 25, "attack": 15}
]
SET enemy = random.choice(enemies)
DISPLAY "A wild " + enemy["name"] + " appears!"
SET hero_attack = 20, rounds = 0
WHILE enemy["hp"] > 0:
enemy["hp"] = enemy["hp"] - hero_attack
rounds = rounds + 1
DISPLAY "Defeated in " + rounds + " rounds!"Write a program that lets the user manage a contact book using a dictionary. The user can: (1) Add a contact (name as key, phone as value), (2) Search for a contact by name, (3) Display all contacts, (4) Exit. Use a while True loop with a menu.
SET contacts = {}
WHILE True:
DISPLAY "1. Add 2. Search 3. Show all 4. Exit"
READ choice
IF choice == "1":
READ name, phone
contacts[name] = phone
ELSE IF choice == "2":
READ name
IF name IN contacts:
DISPLAY contacts[name]
ELSE:
DISPLAY "Not found"
ELSE IF choice == "3":
FOR name, phone IN contacts.items():
DISPLAY name + ": " + phone
ELSE IF choice == "4":
BREAKWrite a program that keeps an event journal. The user can: (1) Add an event (appended with a timestamp to a file "journal.txt"), (2) Read the journal (display all events from the file), (3) Exit. Use with open() in append mode ("a") for writing and read mode ("r") for reading. Check if the file exists before reading.
IMPORT os
WHILE True:
DISPLAY "1. Add event 2. Read journal 3. Exit"
READ choice
IF choice == "1":
READ event from user
WITH open("journal.txt", "a") AS file:
file.write(event + newline)
DISPLAY "Event recorded!"
ELSE IF choice == "2":
IF os.path.exists("journal.txt"):
WITH open("journal.txt", "r") AS file:
DISPLAY file.read()
ELSE:
DISPLAY "No journal found."
ELSE IF choice == "3":
BREAKCongratulations! This is the complete Python Kingdom game with ALL systems: character creation, battle, inventory, shop, dungeon, puzzle room, save/load, and the final boss fight!
The turtle module in Python lets you draw simple graphics. Here are two examples you can add to your game: an HP bar and a mini-map.
HP bar - a green rectangle that shrinks as the hero loses health:
Mini-map - draws dungeon rooms as colored squares:
Copy the turtle code into a separate .py file and run it to see the graphics. The turtle module opens a window with the drawing.
Check how well you understood the lesson with these 6 questions.