Create Your Own Mad Libs Game with Python: In 7 Steps!

Mad Libs Game with Python

Welcome to Project #4 of the Build & Challenge Series!

Today, we’re adding a playful twist by making a Mad Libs game in Python.

Remember those stories where you fill in random words and end up with something completely hilarious?

Now, you’ll create that experience yourself with a simple app that lets users add words to a pre-made story.

It’s easy to build and full of laughs—perfect for sharing with friends!

What you’ll build:

  • Create Your Own Mad Libs Game with Python Main menu
  • Create Your Own Mad Libs Game with Python Add Story
  • Create Your Own Mad Libs Game with Python View Stories
  • Create Your Own Mad Libs Game with Python Play Game
  • Create Your Own Mad Libs Game with Python Final Result

Mad Libs Game with Python

Step 0: Create or Download the CSV File

Purpose of CSV: The CSV file is like a small database where each story template with placeholders is saved. Each row represents a unique story with a title and a template text.

Columns in the CSV:

  • sno: Serial number, which uniquely identifies each story.
  • Title: The title of the story.
  • Story: The story text containing placeholders (e.g., [ADJECTIVE], [NOUN]) that users will replace with their own words.

You can use this CSV:

➡️ Click for the CSV:
sno, Title, Story
1, The Princess, Once upon a time there was a [ADJECTIVE] princess named [PERSONS_NAME] she was from [COUNTRY] she lived in a beautiful kingdom on the hills called [KINGDOM_NAME] she had five [PLURAL_NOUN] while she was [VERB] the horse she fell off of the horse and her dress had a [COLOR] stain on it when she got back to the kingdom she quickly changed to she could wash her dress her [NOUN] told her to come down for dinner after they finished eating they all went to take [PLURAL_VERB] the following day the princess went out to the village to go to the supermarket when she ran into a prince they fel in love and got married and had three children and they lived happily ever after.
2, A Rainy Day, One [ADJECTIVE] day I was walking my [COLOR] pet [NOUN] when [PLURAL_NOUN] started flying from the sky! I called my friend [PERSONS_NAME] and she said one just landed right on her [PLACE] ! [ADVERB] there was raining [PLURAL_NOUN] as well and they were just going everywhere! My [NOUN] started [VERB] and catching [PLURAL_NOUN] with his mouth to eat.
3, Bats Are So Cool!,Bats are so cool! They are [COLOR] [ADJECTIVE] animals which have wings. They like to fly around at [TIME] which makes some people scared of them. But bats are [ADJECTIVE] and they don't want to hurt people. I have a pet bat that lives in [PLACE]. I like to feed him [FOOD] and [FOOD]. He likes to [VERB]. I am his favorite person but he also likes [NOUN]. I want to convince my parents to get me [NUMBER] more bats.
4,My First Day Of School,"Today was my first day of [NUMBER_1_TO_8] grade. My teacher is ms.. She seems [ADJECTIVE] and [ADJECTIVE]. I think her class will be pretty [ADJECTIVE]. My friends [NOUN] and [NOUN] are also in my class. We messed around during class by hiding [NOUN] in peoples' [PLURAL_NOUN] and asking questions about [NOUN]. The teacher got really [ADJECTIVE] at us and told us that we have to go to the [NOUN]. This just made us [VERB] more. It was a [ADJECTIVE] first day of school!"
5,"Birthday Party Fun!","Yesterday I went to [PERSONS_NAME]'s birthday party. I got him/her a [NOUN]. The party was [ADJECTIVE]. We started by playing [ACTIVITY] and then there was a [VERB] party. Lots of my friends were there but I mostly hung out with [PERSONS_NAME]. We talked about [NOUN] and how our friend [PERSONS_NAME] is a [NOUN]. During cake everyone [PAST_TENSE_VERB] and sang [SONG_NAME]. I had a [ADJECTIVE] time at the party and enjoyed celebrating [PERSONS_NAME]. He/she is such a [ADJECTIVE] friend."
6,The New TV Show,The new TV show titled [TITLE]  has taken the world by [NOUN]. It features [NUMBER] [ADJECTIVE] characters including [NAME]  who is a [OCCUPATION] with a secret talent for [VERB_WITH_IN] . Each episode the characters find themselves in [ADJECTIVE] situations like [VERB] in a [PLACE] or having a [ADJECTIVE] showdown with a [NOUN]. The most shocking twist came when [NAME] revealed they were actually a [ADJECTIVE] [ANIMAL] ! Fans can't stop talking about the [ADJECTIVE] [NOUN] that appears in every episode and everyone is dying to know how it all ends. With a [NUMBER] -season arc planned viewers are [VERB_WITH_IN] for more! Join the craze and watch the show to see why it's the [ADJECTIVE] show of the year!

Mad Libs Game with Python Mad Libs Game with Python Mad Libs Game with Python Mad Libs Game with Python Mad Libs Game with Python

Step 1: Create the Main Menu (main_menu Method)

Create the main screen of the app with options to either:

  • Add a New Story: Allows the user to create a new story template.
  • Play Existing Story: Lets the user choose from existing stories in the CSV file.
➡️ Click for the code
from customtkinter import *
import csv
import re

class MadLib(CTk):
    def __init__(self):
        super().__init__()
        self.title("MadLib")
        self.main_menu()
    
    # Step 1: Create main menu
    def main_menu(self):
        self.title_lb = CTkLabel(self, text="Mad Lib!")
        self.title_lb.grid(row=0, column=1, padx=30, columnspan=2)

        self.add_story_btn = CTkButton(self, text="Add Story!", command=self.create_story)
        self.add_story_btn.grid(row=1, column=1, padx=10, pady=10)

        self.existing_story_btn = CTkButton(self, text="Existing Story!", command=self.show_stories)
        self.existing_story_btn.grid(row=1, column=2, padx=10, pady=10)

Mad Libs Game with Python Mad Libs Game with Python Mad Libs Game with Python

  1. Creating the Main Menu: The main_menu method creates two buttons:
    • Add Story Button: Calls the create_story method to allow users to add a new story template.
    • Existing Story Button: Calls the show_stories method to display all the stories saved in the CSV file.
  2. Using CTkLabel and CTkButton: These are part of the customtkinter library, which offers customizable versions of standard Tkinter widgets. Labels (CTkLabel) display static text, while buttons (CTkButton) trigger actions when clicked.

Step 2: Display All Stories (show_stories Method)

This step reads all stories from the CSV file and shows each one as a clickable option for the user.

➡️ Click for the code
    # Step 2: Get all Stories
    def show_stories(self):
        """Fetches all the stories from the csv file"""
        # Clear screen and go back to main menu
        self.clear_screen()
        self.main_menu()

        self.clear_screen()

        # Display title
        title_label = CTkLabel(self, text="Existing Stories")
        title_label.grid(row=0, column=1, padx=30, pady=10, columnspan=2)

        # Read stories from the CSV file
        with open("madlib.csv", "r") as file:
            reader = csv.reader(file)
            for idx, row in enumerate(reader):
                if idx != 0:
                    sid, title, story = row
                    # Display each story title with a 'Play' button
                    title_label = CTkLabel(self, text=f"{sid}. {title}")
                    title_label.grid(row=idx, column=0, padx=10, pady=5)

                    play_btn = CTkButton(self, text="Play", command=lambda story=story: self.play(story))
                    play_btn.grid(row=idx, column=1, padx=10, pady=5)
    

Mad Libs Game with Python Mad Libs Game with Python

  1. Reading the CSV File:
    • The method opens madlib.csv in read mode.
    • It reads each row using csv.reader, where each row contains the story’s serial number (sno), title, and story template.
  2. Displaying Stories:
    • For each story in the CSV, a label displays the story title.
    • A “Play” button is created for each story, allowing users to start playing a particular story.
  3. Lambda Function:
    • Each “Play” button uses a lambda function to call the play method with the corresponding story’s template. This lambda function is necessary because it allows us to pass each story’s content to the play method dynamically.

Step 2.1: clear_screen Helper Method

This method clears all widgets from the screen by iterating over each widget and calling widget.destroy() on it, allowing the app to update the display with new content.

➡️ Click for the code
    # Step 2.1: Helper for all the methods
    def clear_screen(self):
        # Loop through all widgets and destroy them
        for widget in self.winfo_children():
            widget.destroy()

Mad Libs Game with Python Mad Libs Game with Python Mad Libs Game with Python

Step 3: Play the Selected Story (play Method)

Once a user selects a story, this method displays fields for each placeholder in the story template, prompting the user to enter their own words.

➡️ Click for the code
    # Step 3: Play Selected Story
    def play(self, story_data):
        """Let's you play the selected story"""
        self.clear_screen()
        placeholders = set(re.findall(r'\[(\w+)\]', story_data))

        self.entry_fields = {}
        row = 0
        for placeholder in placeholders:
            CTkLabel(self, text=f"Enter {placeholder}").grid(row=row, column=0, padx=10, pady=5)
            entry = CTkEntry(self)
            entry.grid(row=row, column=1, padx=10, pady=5)

            # Save entry field for future reference
            self.entry_fields[placeholder] = entry
            row += 1
        # Button to generate completed story
        submit_btn = CTkButton(self, text="See Story", command=lambda: self.show_completed_story(self.entry_fields, story_data))
        submit_btn.grid(row=row, column=1, padx=10, pady=10)
    

Mad Libs Game with Python

  1. Extracting Placeholders:
    • The re.findall(r'\[(\w+)\]', story_data) line uses regular expressions to identify placeholders within square brackets (like [ADJECTIVE] or [NOUN]).
    • These placeholders are stored in a set (placeholders) to avoid duplicates.
  2. Creating Input Fields for Placeholders:
    • For each placeholder, the code dynamically creates a label and an entry field.
    • Each entry field is saved in a dictionary (self.entry_fields), with the placeholder text as the key. This allows for easy access to user inputs for each placeholder.
  3. Submit Button:
    • A button labeled “See Story” triggers the show_completed_story method. When clicked, it sends both the user inputs and the story template to show_completed_story, which fills in the placeholders with user inputs.

Step 4: Show Completed Story (show_completed_story Method)

This step takes the story template and user inputs, fills in each placeholder, and displays the completed story.

➡️ Click for the code
    # Step 4: Show completed stories
    def show_completed_story(self, input_fields:dict, story:str):
        """Generate the final story by replacing placeholders with user input."""

        # Replace each placeholder in the story with the input from the corresponding entry field
        for placeholder, entry in input_fields.items():
            user_input = entry.get()  # Get the text from the entry field
            story = story.replace(f"[{placeholder}]", user_input)  # Replace placeholder in the story

        # Clear the screen to display the completed story
        self.clear_screen()

        # Display the completed story
        completed_story_label = CTkLabel(self, text="Your Completed Story!")
        completed_story_label.grid(row=0, column=0, padx=20, pady=10, columnspan=2)

        # Show the final story text in a label, breaking lines as needed
        story_text_label = CTkLabel(self, text=story, wraplength=400, justify="left")
        story_text_label.grid(row=1, column=0, padx=20, pady=20, columnspan=2)

        # Button to go back to the main screen or restart
        back_btn = CTkButton(self, text="Back to Menu", command=self.temp)
        back_btn.grid(row=2, column=0, padx=10, pady=10, columnspan=2)

Mad Libs Game with Python Mad Libs Game with Python

  1. Replacing Placeholders:
    • A loop goes through each placeholder, fetching the user input from self.entry_fields[placeholder] using entry.get().
    • The story.replace(f"[{placeholder}]", user_input) line replaces each placeholder with the corresponding user input.
  2. Displaying the Final Story:
    • After replacing all placeholders, the screen is cleared, and the completed story is displayed in a label.
    • A “Back to Menu” button allows users to return to the main menu, calling the temp method.

Step 5: Create New Story (create_story Method)

This step allows users to create and save a new story template into the CSV file.

➡️ Click for the code
    # Step 5: Create new story
    def create_story(self):
        """Let's create a new story. By taking story from user."""
        self.clear_screen()

        # Create label and entry for story title
        title_label = CTkLabel(self, text="Enter Story Title")
        title_label.grid(row=0, column=0, padx=10, pady=10)
        self.title_entry = CTkEntry(self, width=300)
        self.title_entry.grid(row=0, column=1, padx=10, pady=10)

        # Create label and entry for story content
        content_label = CTkLabel(self, text="Enter Story Content")
        content_label.grid(row=1, column=0, padx=10, pady=10)
        self.content_entry = CTkEntry(self, width=300, height=150)
        self.content_entry.grid(row=1, column=1, padx=10, pady=10)

        # Button to save story
        save_btn = CTkButton(self, text="Save Story", command=self.save_story)
        save_btn.grid(row=2, column=1, padx=10, pady=10)

Mad Libs Game with Python Mad Libs Game with Python Mad Libs Game with Python Mad Libs Game with Python

  1. Title and Content Fields:
    • Two entry fields are created, one for the story title and one for the story content.
    • The content can include placeholders to be filled by users when they play the story.
  2. Save Button:
    • A “Save Story” button calls the save_story method, which stores the new story in the CSV file.

Step 6: Save Created Story (save_story Method)

This step handles saving the new story entered by the user to the CSV file.

➡️ Click for the code
    # Step 6: Save Created story
    def save_story(self):
        """Saves created story to the csv."""
        # Get story title and content from entry fields
        story_title = self.title_entry.get()
        story_content = self.content_entry.get()

        # Remove commas and newlines from the story content to avoid CSV format issues
        story_content = re.sub(r"[,\n\r]", "", story_content)

        # Determine the next serial number based on the last entry in the CSV
        try:
            with open("madlib.csv", "r", encoding="utf-8") as file:
                reader = csv.reader(file)
                rows = list(reader)
                if len(rows) > 1:  # Check if there are rows other than the header
                    last_sno = int(rows[-1][0])  # Get the last serial number
                    sno = last_sno + 1
                else:
                    sno = 1  # Start with 1 if no other entries
        except FileNotFoundError:
            # File doesn't exist, start from serial number 1
            sno = 1
        # Append the new story to the CSV file
        with open("madlib.csv", "a", encoding="utf-8") as file:
            writer = csv.writer(file)
            writer.writerow([sno, story_title, story_content])

Mad Libs Game with Python Mad Libs Game with Python

  1. Fetching User Inputs:
    • The title and content entered by the user are retrieved from the entry fields.
  2. Formatting Content:
    • Commas and newline characters are removed from the content to avoid issues with CSV formatting.
  3. Determining Serial Number (sno):
    • If the CSV file already has entries, it reads the last entry to determine the next serial number. If the CSV doesn’t exist, it defaults to serial number 1.
  4. Appending to CSV:
    • The story is saved by appending a new row with sno, title, and content to the CSV file.

Step 6.1: temp Helper Method

This method is a helper to clear the screen and return to the main menu by calling clear_screen and then main_menu.

➡️ Click for the code
    # Step 6.1:Helper For the save story method
    def temp(self):
        self.clear_screen()
        self.main_menu()

Mad Libs Game with Python Mad Libs Game with Python

Step 7: Running the Application

Finally, app = MadLib() creates an instance of the MadLib class, and app.mainloop() starts the main event loop, allowing the application to run continuously, awaiting user input.

app = MadLib()
app.mainloop()

Mad Libs Game with Python Mad Libs Game with Python

Ending Challenge

Challenge Time!

  1. Story Shuffle: Add a random story selector to your game so players get a surprise story every time they play.
  2. Double Trouble: Can you add a “Double Trouble” feature where two players take turns adding words to the same story? The end result? Twice the laughs!
  3. Leaderboard of Laughs: Create a leaderboard where players can rate each story for hilarity or creativity. Who will be crowned the Mad Libs Master?

Full Source Code

Once you’ve nailed the challenge, share your updated version here in the project’s repository GitHub! Let’s grow the project together and learn as a community.

The complete source code is in the GitHub link provided above.

Leave a Reply