Final Project - Quiz Game

Final Project

Build a General Knowledge Quiz Game

You Made It.

You have reached the end of Python Essentials. You have covered variables, data types, strings, lists, dictionaries, sets, tuples, conditionals, loops, functions, scope, and more. Now it is time to put all of it together into one real project.

In this final project you will build a General Knowledge Quiz Game that runs in the console. You will build it step by step, one piece at a time. Each step introduces a new concept from the course and shows you how it fits into a real working program.

By the end you will have a complete, playable quiz game written entirely by you.

What You Will Build

Your finished quiz game will:

Everything you need to build this you have already learned. This project is about connecting the pieces together.

Concepts You Will Use

Step 1 — Set Up Your File

Create a new file in VS Code named quiz_game.py in your final project folder. Add the following comment at the top:

# Python Essentials - Final Project
# General Knowledge Quiz Game
# Your name here

Good habit: always put your name and a description at the top of a project file. It tells anyone reading it what the file is and who wrote it.

Step 2 — Build Your Question Bank

Your questions will be stored in a dictionary. The key is the question and the value is the correct answer. This is a natural fit for a dictionary because every question has exactly one answer.

questions = {
    "What is the capital of France?": "paris",
    "How many sides does a hexagon have?": "6",
    "What is the largest planet in our solar system?": "jupiter",
    "Who wrote Romeo and Juliet?": "shakespeare",
    "What is the chemical symbol for water?": "h2o",
    "How many continents are there on Earth?": "7",
    "What is the fastest land animal?": "cheetah",
    "In what year did World War Two end?": "1945",
    "What is the square root of 144?": "12",
    "Which country invented pizza?": "italy",
    "How many bones are in the adult human body?": "206",
    "What is the longest river in the world?": "nile",
    "Which planet is known as the Red Planet?": "mars",
    "What language has the most native speakers in the world?": "mandarin",
    "How many hours are in a week?": "168",
    "What is the hardest natural substance on Earth?": "diamond",
    "Which ocean is the largest?": "pacific",
    "What is the currency of Japan?": "yen",
    "How many strings does a standard guitar have?": "6",
    "What is the powerhouse of the cell?": "mitochondria"
}

Notice all answers are stored in lowercase. This is intentional and connects to Step 4 where you will learn why.

Why use a dictionary here instead of two separate lists? Because a dictionary keeps the question and answer together as a pair. With two separate lists you would need to track the index manually to match question[0] with answer[0]. A dictionary makes the relationship explicit and the code much cleaner.

Step 3 — Display a Welcome Message

Every good program greets the user. Add a function called show_welcome() that prints a welcome message when the game starts. This is your first function in the project.

def show_welcome():
    print("=" * 40)
    print("   PYTHON ESSENTIALS QUIZ GAME")
    print("=" * 40)
    print("Answer all 20 questions.")
    print("Type your answer and press Enter.")
    print("Answers are not case sensitive.")
    print("=" * 40)

The "=" * 40 is string multiplication — it prints 40 equals signs in one line. A neat trick for creating simple borders in the console.

Call the function below it to test it runs:

show_welcome()

Run the file. You should see your welcome message in the console. Once it works, remove the test call — you will call it properly in Step 8.

Step 4 — Handle Player Input Cleanly

Player input is unpredictable. Someone might type Paris, PARIS, or paris with a space. All of those should be accepted as correct.

Python gives you two string methods to handle this:

Chain them together on the player's input like this:

player_answer = input("Your answer: ").lower().strip()

Because your answers in the dictionary are already lowercase, comparing player_answer to the dictionary value will work correctly regardless of how the player typed their answer.

Why chain .lower() and .strip() directly on input()? Because input() returns a string and you can call string methods directly on it. Chaining them means you do not need to store the raw input in a separate variable first. It is cleaner and more Pythonic.

Step 5 — Build the Quiz Function

Now build the main function that runs the quiz. It takes the questions dictionary as a parameter, iterates over it, asks each question, checks the answer and keeps score.

def run_quiz(questions):
    score = 0
    question_number = 1

    for question, answer in questions.items():
        print(f"\nQuestion {question_number} of {len(questions)}:")
        print(question)
        player_answer = input("Your answer: ").lower().strip()

        if player_answer == answer:
            print("✓ Correct!")
            score += 1
        else:
            print(f"✗ Wrong. The answer was: {answer.title()}")

        question_number += 1

    return score

Walk through this carefully:

Why does score live inside the function? Because of scope. score is a local variable — it only exists inside run_quiz(). This is correct design. The function does its job, counts the score, and returns it. The calling code decides what to do with the result. Keeping score local means it resets cleanly every time the function is called — perfect for a replay feature.

Step 6 — Show the Final Score and Grade

Build a function that takes the score and total number of questions, calculates a percentage, assigns a grade, and displays the result.

def show_results(score, total):
    percentage = (score / total) * 100

    print("\n" + "=" * 40)
    print(f"  GAME OVER")
    print(f"  You scored {score} out of {total}")
    print(f"  Percentage: {percentage:.1f}%")

    if percentage >= 90:
        grade = "A — Excellent!"
    elif percentage >= 70:
        grade = "B — Good work!"
    elif percentage >= 50:
        grade = "C — Not bad."
    elif percentage >= 30:
        grade = "D — Keep practising."
    else:
        grade = "F — Better luck next time."

    print(f"  Grade: {grade}")
    print("=" * 40)

Notice {percentage:.1f} — this formats the float to one decimal place. So 75.0 displays as 75.0% instead of 75.00000000000001%.

Why pass score and total as parameters instead of using global variables? Because functions should receive the data they need through parameters, not reach out into the global scope to grab it. This makes show_results() reusable — you could call it from anywhere with any score and total. If it relied on global variables it would be tightly coupled to this specific program and much harder to reuse or test.

Step 7 — Add a Play Again Loop

Use a while True loop to let the player replay the game without restarting the program. This is the classic use case for while True — keep running until the player decides to stop.

def ask_play_again():
    while True:
        choice = input("\nPlay again? (yes / no): ").lower().strip()
        if choice == "yes":
            return True
        elif choice == "no":
            return False
        else:
            print("Please type yes or no.")

This function validates the input — if the player types anything other than yes or no it keeps asking. This is input validation using while True exactly as you practised in Module 6.

Step 8 — Connect Everything Together

Now build the main function that connects all the pieces. This is where your program actually runs.

def main():
    show_welcome()

    while True:
        score = run_quiz(questions)
        show_results(score, len(questions))

        if not ask_play_again():
            print("\nThanks for playing. Goodbye!")
            break

main()

Walk through the logic:

Why wrap everything in a main() function? Convention and good practice. Putting your program logic inside a main() function means none of it runs automatically when the file is imported by another script. It also makes your code easier to read — anyone looking at your file can see immediately that main() is the entry point. This is how professional Python programs are structured.

The Complete Program

Here is the full quiz game with everything connected. Compare it carefully against what you have built step by step. They should match.

# Python Essentials - Final Project
# General Knowledge Quiz Game

questions = {
    "What is the capital of France?": "paris",
    "How many sides does a hexagon have?": "6",
    "What is the largest planet in our solar system?": "jupiter",
    "Who wrote Romeo and Juliet?": "shakespeare",
    "What is the chemical symbol for water?": "h2o",
    "How many continents are there on Earth?": "7",
    "What is the fastest land animal?": "cheetah",
    "In what year did World War Two end?": "1945",
    "What is the square root of 144?": "12",
    "Which country invented pizza?": "italy",
    "How many bones are in the adult human body?": "206",
    "What is the longest river in the world?": "nile",
    "Which planet is known as the Red Planet?": "mars",
    "What language has the most native speakers in the world?": "mandarin",
    "How many hours are in a week?": "168",
    "What is the hardest natural substance on Earth?": "diamond",
    "Which ocean is the largest?": "pacific",
    "What is the currency of Japan?": "yen",
    "How many strings does a standard guitar have?": "6",
    "What is the powerhouse of the cell?": "mitochondria"
}


def show_welcome():
    print("=" * 40)
    print("   PYTHON ESSENTIALS QUIZ GAME")
    print("=" * 40)
    print("Answer all 20 questions.")
    print("Type your answer and press Enter.")
    print("Answers are not case sensitive.")
    print("=" * 40)


def run_quiz(questions):
    score = 0
    question_number = 1

    for question, answer in questions.items():
        print(f"\nQuestion {question_number} of {len(questions)}:")
        print(question)
        player_answer = input("Your answer: ").lower().strip()

        if player_answer == answer:
            print("✓ Correct!")
            score += 1
        else:
            print(f"✗ Wrong. The answer was: {answer.title()}")

        question_number += 1

    return score


def show_results(score, total):
    percentage = (score / total) * 100

    print("\n" + "=" * 40)
    print(f"  GAME OVER")
    print(f"  You scored {score} out of {total}")
    print(f"  Percentage: {percentage:.1f}%")

    if percentage >= 90:
        grade = "A — Excellent!"
    elif percentage >= 70:
        grade = "B — Good work!"
    elif percentage >= 50:
        grade = "C — Not bad."
    elif percentage >= 30:
        grade = "D — Keep practising."
    else:
        grade = "F — Better luck next time."

    print(f"  Grade: {grade}")
    print("=" * 40)


def ask_play_again():
    while True:
        choice = input("\nPlay again? (yes / no): ").lower().strip()
        if choice == "yes":
            return True
        elif choice == "no":
            return False
        else:
            print("Please type yes or no.")


def main():
    show_welcome()

    while True:
        score = run_quiz(questions)
        show_results(score, len(questions))

        if not ask_play_again():
            print("\nThanks for playing. Goodbye!")
            break

main()

Challenges — Take It Further

If you want to push further, try these extensions on your own:

Challenge 1 — Shuffle the Questions

  • Import the random module at the top of your file: import random
  • Convert the dictionary to a list of tuples, shuffle it, and iterate over that instead:
import random

def run_quiz(questions):
    score = 0
    question_number = 1
    question_list = list(questions.items())
    random.shuffle(question_list)

    for question, answer in question_list:
        # rest of your code unchanged

Now the questions appear in a different order every game.

Challenge 2 — Ask for the Player's Name

  • Before the quiz starts ask the player for their name using input()
  • Use it in the welcome message and the results screen
  • Pass the name as a parameter to show_welcome() and show_results()

Challenge 3 — Track the High Score

  • Create a variable high_score = 0 in the global scope
  • After each game compare the score to the high score
  • Use the global keyword inside a function to update it
  • Display the high score on the results screen
  • This directly practices what you learned about the global keyword in Module 7

Challenge 4 — Add Your Own Questions

  • Replace any of the 20 questions with your own
  • Add questions about Python itself — what better way to test what you learned?

What You Just Demonstrated

By completing this project you have shown you can:

That is not a beginner skill set anymore.

🎓 Congratulations

You have completed Python Essentials. You started with variables and data types and you finished by building a complete console application using dictionaries, functions, loops, conditionals, scope, and string manipulation.

Python is a language you learn by building things. You have proven you can do that. The best next step is to keep building — something slightly harder than what you just finished. That is how developers grow.

Well done. Now go build something.

Don't Forget to commit and Push!