Python Adventure Projects
Every level teaches concepts — projects put them together. Kids build 13 real Python programs, from a first Name Greeter to a full Capstone Showcase, and code freely in the live Playground.
13 Mini-Projects — Build Real Python Programs
The classic first project every programmer builds. A program that asks for your name and says hello — but you write every line yourself! Simple, real, and satisfying.
What you build
- Ask the user to enter their name with
input() - Store the answer in a variable
- Print a personalized greeting with
print() - Works for any name — it's interactive!
Skills needed first
Build a real quiz game that asks questions, checks answers, and keeps score. The program makes decisions with if/else and repeats with a for loop — just like a real app.
What you build
- A list of questions and correct answers
- Loop through each question with
for - Check the player's answer with
if/else - Add 1 to the score for each correct answer
- Show the final score at the end
Skills needed first
The most powerful project — a text analysis tool! Type any sentence and the program counts words, finds the longest one, and stores frequency data in a dictionary.
What you build
- A
deffunction that splits text into a list of words - Count words with
len() - Find the longest word with a
forloop - Count word frequency using a dictionary
- Format and display results with f-strings
Skills needed first
🎯 Goal: Build a command-line diary program. Users can add new entries and view everything they've written so far, with every entry safely saved to a file between runs.
Skills needed first
✅ Requirements
- Use a
whileloop to show a menu with Add Entry, View Entries, and Quit - Add Entry appends the new text to
diary.txtwith a newline - View Entries opens
diary.txtand prints every saved line - A missing
diary.txtis handled safely with try/except instead of crashing - Every file operation uses
with open(...)
💻 Starter Code
💡 Hint
add_entry, open the file in append mode: with open("diary.txt", "a") as f: then f.write(text + "\n"). Inside view_entries, put the file-reading code inside a try block, and catch FileNotFoundError in the except block to print a friendly message instead of crashing.▶ Expected Output
This is an example run — your own entries and menu choices will differ.
🔍 Self-Check
- Running the program twice keeps old entries instead of overwriting them
- Deleting
diary.txtand choosing View Entries prints a friendly message instead of crashing - The menu keeps looping until Quit is chosen
- Every file operation uses
with open()
🎯 Goal: Combine the bubble sort algorithm with string formatting to literally watch the sort happen — each pass prints the list as a bar chart made of asterisks, one bar per number.
Skills needed first
✅ Requirements
- Write
bar_chart(numbers)that turns each number into a string of that many asterisks - Write
bubble_sort_visual(numbers)that performs a full bubble sort - Print the bar chart again after every completed pass
- Print the final, fully sorted list at the end
💻 Starter Code
💡 Hint
n is just the asterisk character repeated n times using the multiplication operator: "*" * n . For the swap step, reuse the exact bubble sort pattern: compare the numbers at index i and i + 1, and swap them if the first one is bigger.▶ Expected Output
🔍 Self-Check
bar_chart(5)produces a string of exactly 5 asterisks, no more, no less- Each pass prints a chart a little closer to sorted than the last
- The final printed list is fully sorted from smallest to largest
- Changing
heightsto a brand new list of 5 numbers still visualizes correctly
🎯 Goal: Instead of writing one big script, split reusable logic into your own module. Build 3 utility functions, prove each one works with an assert test, then import the whole module into a separate demo script.
Skills needed first
✅ Requirements
- Create at least 3 utility functions in their own module file,
toolkit.py - Write at least one
asserttest for each function, inside the module itself - Create a second file that imports the module and calls each function
- Running the module by itself prints a self-tests-passed confirmation
💻 Starter Code
Save as toolkit.py:
Save as demo.py, in the same folder:
💡 Hint
is_even can use the modulo operator to check for a remainder of zero. reverse_string can use slicing to reverse a string. average is simply the sum of the numbers divided by how many there are. In demo.py , call functions through the module name, exactly like toolkit.is_even(10).▶ Expected Output
Run toolkit.py by itself first to confirm the self-tests pass, then run demo.py — it prints the same self-test line again because importing a module runs its code once.
🔍 Self-Check
toolkit.pyruns on its own with noAssertionErrordemo.pysuccessfully importstoolkitand calls all 3 functions- Every function has at least one assert test proving it works
- A 4th utility function could be added following the exact same pattern
🎯 Goal: Fetch a random inspirational quote from a live web API using the requests library and JSON parsing — and if the request fails for any reason, fall back to a local list so the program never crashes.
Skills needed first
✅ Requirements
- Write
get_quote_from_api()that calls a web API and returns a formatted quote string - Keep a
FALLBACK_QUOTESlist with at least 3 quotes - Write
get_daily_quote()that tries the API first and falls back safely if anything goes wrong - The program never crashes, even with no internet connection
💻 Starter Code
💡 Hint
get_quote_from_api() in a try block, and return its result if it works. In the except block, catch the general Exception type (since many different things could go wrong — no internet, a missing library, or a bad response) and return random.choice(FALLBACK_QUOTES) instead.▶ Expected Output
The exact quote differs if your computer is online and the requests package is installed — the example above shows the offline fallback path.
🔍 Self-Check
- Turning off Wi-Fi (or breaking the
requestsimport on purpose) still produces a quote instead of crashing get_daily_quote()never lets an exception escape to whatever calls it- The fallback list has at least 3 different quotes
- The API version combines the response's content and author fields into one readable string
🎯 Goal: The classic capstone project — build the full working version of the Contact Book concept from the game. A menu lets the user add, list, and delete contacts, and everything is saved to a JSON file so contacts survive between runs.
Skills needed first
✅ Requirements
- Load existing contacts from a JSON file when the program starts
- Menu options to add, list, and delete a contact
- Save contacts back to the JSON file after every add or delete
- Listing with zero contacts prints a friendly message instead of nothing
- Deleting a name that isn't in the contact book doesn't crash the program
💻 Starter Code
💡 Hint
load_contacts should open the file only if it already exists, then use json.load(f) to turn its contents back into a dictionary. save_contacts should use json.dump(contacts, f) to write the whole dictionary back out. delete_contact should check if the name is a key in the dictionary before trying to remove it.▶ Expected Output
🔍 Self-Check
- Adding a contact, quitting, and restarting the program still shows that contact (real file persistence)
- Listing with zero contacts prints a friendly message instead of nothing
- Deleting a name that doesn't exist doesn't crash the program
contacts.jsoncontains valid JSON you could open in a text editor
🎯 Goal: Combine file save and load with a sorting algorithm: save tasks with a priority number to a text file, then sort them with bubble sort so the most urgent task always prints first.
Skills needed first
✅ Requirements
- Load previously saved tasks from a text file when the program starts
- Save every task, with its priority number, back to the text file
- Sort tasks by priority using bubble sort before printing them
- The most urgent task (lowest priority number) prints first
💻 Starter Code
💡 Hint
tasks[i] and tasks[i + 1] by their priority number (the second item in each tuple), and swap the two tuples if the first one's priority is bigger.▶ Expected Output
🔍 Self-Check
- Tasks print in priority order, lowest number first
todo.txtsurvives being closed and reopened in the same format- Deleting
todo.txtand running the program again doesn't crash - The sort uses the same swap pattern as bubble sort, just comparing priority numbers instead
🎯 Goal: Build a tiny text adventure where rooms are stored as a dictionary of dictionaries. Every time the player moves, a custom decorator logs the direction before the move actually happens.
Skills needed first
✅ Requirements
- Store rooms as a dictionary of dictionaries, each with a description and possible directions
- Write a
log_movedecorator that prints the direction before every move - Apply the decorator to the
move()function with@log_move - Moving in a direction that doesn't exist prints a friendly message instead of crashing
💻 Starter Code
💡 Hint
wrapper , print a message that includes the direction — remember direction is the second argument, so it's args[1] . Then call the original function with func(*args, **kwargs) and return whatever it returns, so the decorator doesn't change how move() behaves.▶ Expected Output
🔍 Self-Check
- Every call to
move()prints which direction the player is moving in before showing the room - Walking toward a direction that isn't listed for the current room prints a friendly message instead of crashing
- A new room can be added to the
roomsdictionary without changing any function code - The decorator still returns the correct next room name to the rest of the program
🎯 Goal: Write a password strength checker that uses regular expressions to check for length, uppercase and lowercase letters, digits, and symbols — then prove your checker is correct with a set of assert-based test cases.
Skills needed first
✅ Requirements
- Score a password based on length, uppercase, lowercase, digits, and symbols
- Use the
remodule and regular expressions for every check - Return
"Weak","Medium", or"Strong"based on the total score - Prove the checker works with at least 4
assertstatements before trusting it
💻 Starter Code
💡 Hint
if blocks using re.search() — one that looks for a digit with the pattern r"\d", and one that looks for a symbol using a character class containing the symbols you want to accept, like r"[!@#$%^&*]" . Each match should add 1 to score, exactly like the checks already written for uppercase and lowercase letters.▶ Expected Output
🔍 Self-Check
- All 4 assert statements pass with no
AssertionError - A password with only lowercase letters scores
"Weak" - Adding an uppercase letter, a digit, and a symbol can raise a password all the way to "Strong"
- Every regex pattern is written as a raw string starting with
r
🎯 Goal: Parse JSON weather data for three different cities and print a clean, formatted report for each one — the same pattern you'd use to display data pulled from a real weather API.
Skills needed first
✅ Requirements
- Write
parse_city()that turns one JSON string into a dictionary - Write
print_report()that prints a one-line formatted summary for a city - Loop through all 3 cities in
CITY_DATAand print a report for each - Output format matches: city name, temperature, and condition
💻 Starter Code
💡 Hint
parse_city() is a one-line function: it just returns json.loads(json_text). print_report() builds one f-string using the three dictionary keys — city, temp_c, and condition — and prints it.▶ Expected Output
🔍 Self-Check
parse_city()returns a real dictionary you can index with square bracketsprint_report()'s output format matches exactly: city name, temperature, comma, condition- All 3 cities print without errors
- You can explain where a real
requests.get(...).json()call would replace the pretendCITY_DATAlist
🎯 Goal: Pick your own idea and build something bigger. This is a template, not a fixed assignment: follow the requirements checklist to combine file handling with at least one of an API call, a search/sort algorithm, or a class, to build the most ambitious program of the whole course.
Skills needed first
✅ Requirements
- At least one file operation (read or write) using
with open() - At least one
try/exceptblock that prevents a real crash - At least one of: a live API call with
requestsandjson, a search/sort algorithm, or a class (OOP) - At least 2 custom functions or methods that work together
- At least 1
asserttest proving a piece of your project works - The whole program runs start to finish with no errors
💻 Starter Code
💡 Hint
▶ Expected Output
🔍 Self-Check
- At least one file operation using
with open() - At least one
try/exceptblock that actually prevents a crash - At least one of: an API call, a search/sort algorithm, or a class
- At least 2 custom functions or methods, connected together
- At least 1
asserttest - The whole program runs start to finish with no errors or crashes
🖥️ Python Playground
A live in-browser Python editor powered by Skulpt. No installation needed — write and run Python code instantly.
Frequently Asked Questions
What projects do kids build in Python Adventure?
How hard are the Python Adventure projects?
Does Python Adventure have a live code editor?
Can I run the project code outside the browser?
🐍 Start Building Today!
Complete the Explorer Zone levels and unlock your first real Python project — free, no sign-up needed.
▶ Play Python Adventure Free 📚 See All Topics →
Python Adventure