Project Tutorial: Build a Python Word Guessing Game
In this tutorial, I'll guide you through creating a word-guessing game similar to Wordle using Python. While many coding projects focus on data analysis, building a game is not only fun but also helps reinforce fundamental programming concepts in a creative context. Game development is particularly excellent for practicing object-oriented programming, thinking logically, and creating interactive user experiences.
By the end of this tutorial, you'll have built a fully functional word guessing game where:
- Players try to guess a mystery word within a limited number of attempts
- Correct letters in the correct position are revealed
- Players get feedback on misplaced and incorrect letters
- The game tracks win and loss conditions
What You'll Learn
Through this project, you'll practice:
- Working with Python's built-in modules like
random
- Using file I/O to read external data
- Creating and managing game loops
- Implementing conditional logic for game rules
- Handling user input and providing feedback
- Building a text-based user interface
Before You Start: Pre-Instruction
To make the most of this project walkthrough, follow these preparatory steps:
- Review the Project
Access the project and familiarize yourself with the goals and structure: Word Guessing Game Project. - Prepare Your Environment
- If you're using the Dataquest platform, everything is already set up for you.
- If you're working locally, ensure you have Python and Jupyter Notebook installed.
- Get Comfortable with Jupyter
- New to Markdown? We recommend learning the basics to format headers and add context to your Jupyter notebook: Markdown Guide.
- For file sharing and project uploads, create a GitHub account ahead of the webinar: Sign Up on GitHub.
Setting Up Your Environment
Working with Jupyter Notebook
For this project, we'll use Jupyter Notebook, which allows us to write and execute Python code in an interactive environment. If you're new to Jupyter, here's a quick overview:
- Cells: Jupyter notebooks consist of cells that can contain either code or markdown (formatted text).
- Running Cells: To execute a cell, select it and press Shift+Enter.
- Cell Types:
- Code cells: Where you write and execute Python code
- Markdown cells: Where you write formatted text (like this tutorial)
Project Resources
For this project, you'll need:
- A text file containing words for your game (we'll provide a simple version)
- The Jupyter notebook to write your game code
Let's create the required files:
-
Create a new file called
words.txt
and add words (one per line). Here's the sample list we'll be using in this walkthrough:bears kings helps learn queen twist happy
-
Create a new Jupyter notebook named
Word_Raider.ipynb
With our environment set up, we're almost ready to start building our game but first, let’s understand some key concepts.
Understanding Game Loops
One of the key concepts in this project is the game loop, which is fundamental to most interactive applications and games. Let's break down how it works:
- The Loop Condition: Our loop continues as long as
used_turns < max_turns
, ensuring the game stops when the player runs out of turns. - Input Phase: We collect and validate player input at the start of each loop iteration.
- Update Phase: We process the guess, update our game state (tracking correct, incorrect, and misplaced letters).
- Render Phase: We display the current state of the game (the partially revealed word, tracked letters, and turns remaining).
- Win/Loss Check: After processing a guess, we check if the player has won or lost, and break the loop if either condition is met.
This pattern of input → update → render → check game state is common across many types of games, from simple text-based games like ours to complex 3D video games.
Now, that we understand these key concepts, let’s get started with the project.
Project Implementation
Step 1: Importing Required Libraries
Let's start by importing the random
module, which will allow us to randomly select a word from our word bank:
import random
Learning Insight: Always place your import statements at the top of your code. This makes your dependencies clear to anyone reading your code and ensures they're available throughout your program.
Step 2: Creating Global Variables
Next, let's define some global variables that will be used throughout our game:
game_name = "Word Raider"
word_bank = []
Here we're:
- Setting the name of our game to "Word Raider" (feel free to choose your own name!)
- Creating an empty list that will store all the possible words for our game
Step 3: Loading the Word Bank
Now, let's load our word list from the text file we created earlier:
with open("words.txt") as word_file:
for line in word_file:
word_bank.append(line.rstrip().lower())
# Verify our word bank loaded correctly
word_bank
Output:
['bears', 'kings', 'helps', 'learn', 'queen', 'twist', 'happy']
Learning Insight: Using a context manager (
with
statement) is the recommended way to open files in Python. It ensures the file is properly closed after use, even if an error occurs. The.rstrip()
method removes trailing whitespace (like newline characters), and.lower()
standardizes all words to lowercase for consistency.
Step 4: Selecting the Target Word
With our word bank populated, we can randomly select a word for the player to guess:
selected_word = random.choice(word_bank)
Learning Insight: The
random.choice()
function selects a random item from a sequence (in this case, our list of words). This introduces variability into our game, ensuring a random word is selected each time the game is played, increasing replay value.
Step 5: Setting Up Game Information
Before we start the main game loop, let's define some variables to track the game state:
# Defining game information
incorrect_letters = []
misplaced_letters = []
max_turns = 6
used_turns = 0
These variables will help us track:
- Letters guessed that aren't in the word (
incorrect_letters
) - Letters guessed that are in the word but in the wrong position (
misplaced_letters
) - The maximum number of guesses allowed (
max_turns
) - How many guesses the player has used so far (
used_turns
)
Step 6: Creating the User Interface
Let's provide some initial information to the player:
print(f"Welcome to {game_name}!")
print(f"The word to guess has {len(selected_word)} letters.")
print(f"You have {max_turns} turns to guess the word!")
Output:
Welcome to Word Raider!
The word to guess has 5 letters.
You have 6 turns to guess the word!
Learning Insight: F-strings (formatted string literals) are a convenient way to embed expressions inside string literals. They begin with an 'f' and use curly braces
{}
to include variable values or expressions in your strings. F-strings were introduced in Python 3.6 and are more readable and generally faster than older string formatting methods.
Step 7: Building the Main Game Loop
Now we're ready to build the core of our game: the main loop that will handle player input, game logic, and win/loss conditions.
Let's start with the basic structure that handles user input:
# Main game loop
while used_turns < max_turns:
guess = input("Guess a word (or type 'stop' to end game):").lower().strip()
if guess == "stop":
break
This sets up a loop that continues until the player has used all their turns. We also provide an escape option by allowing the player to type "stop" to end the game at any time.
Learning Insight: When using
while
loops, it's important to have a clear condition that will eventually becomeFalse
(in this case,used_turns < max_turns
). It's also good practice to include a way to break out of the loop manually (like our "stop" command) to prevent the game from running indefinitely.
Step 8: Validating User Input
Next, let's add validation to ensure the player's guess is a valid word of the correct length:
# Main game loop with input validation
while used_turns < max_turns:
guess = input("Guess a word (or type 'stop' to end game):").lower().strip()
if guess == "stop":
break
if len(guess) != len(selected_word) or not guess.isalpha():
print(f"Please enter a {len(selected_word)} letter word.")
continue
Learning Insight: The
isalpha()
method checks if a string contains only alphabetical characters (A-Z or a-z). This validation ensures that players enter actual words (no numbers, spaces, or special characters) of the correct length. Thecontinue
statement skips the rest of the current loop iteration and starts the next one, effectively asking for a new guess.
Step 9: Initial Letter Processing
Now, let's add the basic logic to evaluate the player's guess against the target word:
# Main game loop with basic letter processing
while used_turns < max_turns:
guess = input("Guess a word (or type 'stop' to end game):").lower().strip()
if guess == "stop":
break
if len(guess) != len(selected_word) or not guess.isalpha():
print(f"Please enter a {len(selected_word)} letter word.")
continue
index = 0
for letter in guess:
if letter == selected_word[index]:
print(letter, end=' ')
elif letter in selected_word:
misplaced_letters.append(letter)
print("_", end=' ')
else:
incorrect_letters.append(letter)
print("_", end=' ')
index += 1
print("\n")
print(f"Misplaced letters: {misplaced_letters}")
print(f"Incorrect letters: {incorrect_letters}")
This basic implementation checks each letter in the guess and:
- Displays the letter if it's in the correct position
- Adds it to misplaced letters and displays an underscore if it's in the word but in the wrong position
- Adds it to incorrect letters and displays an underscore if it's not in the word at all
Learning Insight: We use indexing to compare characters at the same position in both strings. The index variable keeps track of our position in the target word as we iterate through the guess. This is a common technique for comparing elements at corresponding positions in different sequences.
However, you might notice an issue when running this code. If a letter appears multiple times in a player's guess, it will be added to our tracking lists multiple times. Let's fix that next.
Step 10: Handling Duplicate Letters
To improve our game's feedback system, we need to handle duplicate letters more intelligently:
# Accounting for duplicates in misplaced/incorrect letter lists
while used_turns < max_turns:
guess = input("Guess a word (or type 'stop' to end game):").lower().strip()
if guess == "stop":
break
if len(guess) != len(selected_word) or not guess.isalpha():
print(f"Please enter a {len(selected_word)} letter word.")
continue
index = 0
for letter in guess:
if letter == selected_word[index]:
print(letter, end=' ')
if letter in misplaced_letters:
misplaced_letters.remove(letter)
elif letter in selected_word:
if letter not in misplaced_letters:
misplaced_letters.append(letter)
print("_", end=' ')
else:
if letter not in incorrect_letters:
incorrect_letters.append(letter)
print("_", end=' ')
index += 1
print("\n")
print(f"Misplaced letters: {misplaced_letters}")
print(f"Incorrect letters: {incorrect_letters}")
The key improvements here are:
-
Removing letters from
misplaced
when they're found in the correct position:
If a player first guesses a letter in the wrong position and then later in the correct position, we remove it from themisplaced_letters
list since it's no longer misplaced.if letter == selected_word[index]: print(letter, end=' ') if letter in misplaced_letters: misplaced_letters.remove(letter)
-
Preventing duplicate entries in our tracking lists:
We only add a letter to our tracking lists if it's not already there, keeping our feedback clean and easy to read.elif letter in selected_word: if letter not in misplaced_letters: misplaced_letters.append(letter)
Learning Insight: Managing state is a key component of interactive applications. As our game progresses, we need to ensure our tracking data stays accurate and helpful. This kind of state management is valuable practice for more complex programming tasks where maintaining consistent data is required.
Step 11: Adding Win and Loss Conditions
Finally, let's complete our game by adding win and loss conditions:
# Complete game loop with win/loss conditions
while used_turns < max_turns:
guess = input("Guess a word (or type 'stop' to end game):").lower().strip()
if guess == "stop":
break
if len(guess) != len(selected_word) or not guess.isalpha():
print(f"Please enter a {len(selected_word)} letter word.")
continue
index = 0
for letter in guess:
if letter == selected_word[index]:
print(letter, end=' ')
if letter in misplaced_letters:
misplaced_letters.remove(letter)
elif letter in selected_word:
if letter not in misplaced_letters:
misplaced_letters.append(letter)
print("_", end=' ')
else:
if letter not in incorrect_letters:
incorrect_letters.append(letter)
print("_", end=' ')
index += 1
print("\n")
# Win condition
if guess == selected_word:
print("\nCongratulations you guessed the word!")
break
used_turns += 1
# Loss condition
if used_turns == max_turns:
print(f"\nGame over, you lost. The word was: {selected_word}")
break
print(f"Misplaced letters: {misplaced_letters}")
print(f"Incorrect letters: {incorrect_letters}")
print(f"You have {max_turns - used_turns} turns left.")
Learning Insight: It's important to check the win condition before incrementing
used_turns
. This ensures the player wins instantly when they guess correctly, without unnecessarily counting that guess as a used turn.
The Complete Game
Let's put it all together into a single code block for ease of implementation:
import random
# Set up game variables
game_name = "Word Raider"
word_bank = []
# Load words from file
with open("words.txt") as word_file:
for line in word_file:
word_bank.append(line.rstrip().lower())
# Select target word
selected_word = random.choice(word_bank)
# Initialize game state
incorrect_letters = []
misplaced_letters = []
max_turns = 6
used_turns = 0
# Display game introduction
print(f"Welcome to {game_name}!")
print(f"The word to guess has {len(selected_word)} letters.")
print(f"You have {max_turns} turns to guess the word!")
# Main game loop
while used_turns < max_turns:
guess = input("Guess a word (or type 'stop' to end game):").lower().strip()
if guess == "stop":
break
if len(guess) != len(selected_word) or not guess.isalpha():
print(f"Please enter a {len(selected_word)} letter word.")
continue
index = 0
for letter in guess:
if letter == selected_word[index]:
print(letter, end=' ')
if letter in misplaced_letters:
misplaced_letters.remove(letter)
elif letter in selected_word:
if letter not in misplaced_letters:
misplaced_letters.append(letter)
print("_", end=' ')
else:
if letter not in incorrect_letters:
incorrect_letters.append(letter)
print("_", end=' ')
index += 1
print("\n")
# Win condition
if guess == selected_word:
print("\nCongratulations you guessed the word!")
break
used_turns += 1
# Loss condition
if used_turns == max_turns:
print(f"\nGame over, you lost. The word was: {selected_word}")
break
print(f"Misplaced letters: {misplaced_letters}")
print(f"Incorrect letters: {incorrect_letters}")
print(f"You have {max_turns - used_turns} turns left.")
Playing the Game
Here's an example of a gameplay session:
Welcome to Word Raider!
The word to guess has 5 letters.
You have 6 turns to guess the word!
Guess a word (or type 'stop' to end game): hellooo
Please enter a 5 letter word.
Guess a word (or type 'stop' to end game): hello
h _ l _ _
Misplaced letters: ['l']
Incorrect letters: ['e', 'o']
You have 5 turns left.
Guess a word (or type 'stop' to end game): helps
h e l p s
Congratulations you guessed the word!
Next Steps and Enhancements
Now that you've built a working word guessing game, here are some ideas to enhance and extend it:
- Variable Word Length: Modify your game to work with words of different lengths.
- Hard Mode: Implement a Wordle-style "hard mode" where letters that have been correctly guessed must be used in subsequent guesses.
- Dictionary Validation: Only accept guesses that are real words by checking against a dictionary.
- Custom Word Categories: Allow players to select word categories (animals, countries, etc.).
- Graphical User Interface: Use a library like Pygame to create a visual interface.
- Scoring System: Add a scoring system based on how quickly the player guesses the word.
We have some other project walkthrough tutorials you may also enjoy:
- Project Tutorial: Build Your First Data Project
- Project Tutorial: Profitable App Profiles for the App Store and Google Play Markets
- Project Tutorial: Investigating Fandango Movie Ratings
- Project Tutorial: Analyzing New York City High School Data
- Project Tutorial: Analyzing Helicopter Prison Escapes Using Python
- Project Tutorial: Predicting Heart Disease with Machine Learning
- Project Tutorial: Customer Segmentation Using K-Means Clustering
Review
In this tutorial, we've built a word-guessing game from scratch using Python. Along the way, we've practiced key programming concepts including:
- Using Python's built-in modules
- File I/O operations
- String manipulation
- Using loops and conditionals
- Input validation and processing
- Game state management
Game development is an excellent way to improve your programming skills while creating something fun and interactive. The concepts you've learned here, particularly state management and game loops, form the foundation of many other games and applications.
If you're new to Python or finding some concepts in this tutorial challenging, our Python Basics for Data Analysis course will help you learn the foundational skills needed for this project. The course covers essential topics like loops, conditionals, and string manipulation that we've used extensively in this game. Once you're comfortable with these concepts, come back to build your own Word Raider game and take on the enhancement challenges!