Are you ready to create a fun and interactive game in Python? Imagine building a classic Word Guesser game where players can guess letters, reveal hints, and even upload their own word lists. It’s a perfect project for beginners looking to sharpen their coding skills with a hands-on challenge.
Today, you’ll learn how to build a Word Guesser game using Python’s tkinter library. We’ll walk through the process of setting up the game’s interface, handling user guesses, and creating a simple, yet engaging experience.
Let’s get started!
Table of Contents
- Necessary Libraries
- Imports
- Displaying Guessed and Hidden Letters
- Handling Player Guesses
- Revealing Hints and Managing Game Updates
- Ending and Restarting the Game
- The Upload Word List Function
- Game Setup and Initialization
- Example
- Full Code
Necessary Libraries
To get this code up and running smoothly, you’ll need to install the tkinter library using your terminal or command prompt:
$ pip install tk
Imports
import tkinter as tk
from tkinter import filedialog, messagebox
import random
Before diving into our code, we need to make sure we’re fully prepared. Let’s start by gathering our tools:
Since we’re building a game, we need a graphical interface, which is where the Tkinter library comes in. We’ll import filedialog
to allow file uploads and messagebox
to show information through pop-up messages.
As our goal is to create a word guesser game, we’ll also import random
to help us select words at random and provide hints when needed.
Displaying Guessed and Hidden Letters
def display_word(word, guessed_letters):
"""Display the word with unguessed letters as underscores."""
return " ".join([letter if letter in guessed_letters else '_' for letter in word])
This is where the magic happens! The display_word()
function is what reveals the letters you’ve guessed so far and hides the ones you haven’t. It looks at each letter in the word, checks if you’ve guessed it, and if you have, it shows the letter. If not, it replaces it with an underscore—simple as that!
Handling Player Guesses
How is the guessed_letters
set formed?
Well, it starts with the process_guess()
function. When the user types a letter, this function grabs it, converts it to lowercase, and gets ready to validate it.
guess = guess_entry.get().lower()
guess_entry.delete(0, tk.END)
What happens if the input isn’t valid?
If the user enters something other than a single letter, like a number or more than one character, the game gently tells them to try again with a valid letter.
if len(guess) != 1 or not guess.isalpha():
message_label.config(text="Please enter a valid letter.")
return
What if the user already guessed that letter?
No one likes repeating guesses, so if they already guessed the letter, the game will let them know that they’ve tried it before.
if guess in guessed_letters:
message_label.config(text=f"You already guessed '{guess}'.")
When the guess is correct:
If the guessed letter is part of the word, it’s added to the guessed_letters
set, and the player gets a nice “Good job!” message.
elif guess in word:
guessed_letters.add(guess)
message_label.config(text=f"Good job! '{guess}' is in the word.")
When the guess is wrong:
If the guess is incorrect, the number of attempts left decreases by 1, and the player is informed about the incorrect guess.
else:
attempts -= 1
message_label.config(text=f"Sorry, '{guess}' is not in the word.")
Updating the game state:
Finally, the process_guess()
function wraps things up by calling the update_game_state()
function to check if the game is won or lost, and refreshes the display accordingly.
update_game_state()
Revealing Hints and Managing Game Updates
Guessing a word when you only know the number of letters and have a limited number of attempts can be tough. To give you a bit of a break, we have the show_hint()
function. It looks at the letters you haven’t guessed yet, picks one at random, and reveals it.
We also reduce your attempts by 1. If there are no more letters left to reveal, it lets you know that hints are used up. lastly, it calls the update_game_state()
function to refresh the game and check if you’ve won or lost.
def show_hint():
"""Reveal a random letter from the word as a hint."""
global word, guessed_letters, attempts, message_label
available_letters = [letter for letter in word if letter not in guessed_letters]
if available_letters:
hint_letter = random.choice(available_letters)
guessed_letters.add(hint_letter)
attempts -= 1
message_label.config(text=f"Hint: The letter '{hint_letter}' has been revealed!")
update_game_state()
else:
message_label.config(text="No more letters to reveal.")
With all these changes happening, we need to keep the game’s display up-to-date. That’s where the update_game_state()
function comes in. It updates both the word display and the number of remaining attempts. Additionally, it checks if the game has been won or lost. If you’ve guessed the word, it congratulates you. If you’ve run out of attempts, it reveals the word and ends the game.
def update_game_state():
"""Update the game display and check for win/loss conditions."""
global word, guessed_letters, attempts, word_label, attempts_label, message_label, guess_entry, hint_button, restart_button
word_label.config(text=display_word(word, guessed_letters))
attempts_label.config(text=f"Attempts left: {attempts}")
if all(letter in guessed_letters for letter in word):
message_label.config(text=f"Congratulations! You've guessed the word '{word}'.")
end_game()
elif attempts == 0:
word_label.config(text=word)
message_label.config(text=f"Game Over! The word was '{word}'.")
end_game()
Ending and Restarting the Game
When the game wraps up, whether you’ve guessed the word or run out of attempts, the end_game()
function steps in to finish things off. It disables the input and hint buttons to stop any more guesses and lights up the restart button so you can jump back in and give it another go.
def end_game():
"""Disable input and show restart button when the game ends."""
guess_entry.config(state=tk.DISABLED)
hint_button.config(state=tk.DISABLED)
restart_button.config(state=tk.NORMAL)
And when you hit the restart button, the restart_game()
function springs into action. It selects a new word from the list, resets the guessed letters, and brings your attempts back to 6. It also updates the display and reactivates the inputs so you can jump right back into the game.
def restart_game():
"""Restart the game with a new random word."""
global word, guessed_letters, attempts, word_list
word = random.choice(word_list)
guessed_letters = set()
attempts = 6
word_label.config(text=display_word(word, guessed_letters))
attempts_label.config(text=f"Attempts left: {attempts}")
message_label.config(text="")
guess_entry.config(state=tk.NORMAL)
hint_button.config(state=tk.NORMAL)
restart_button.config(state=tk.DISABLED)
The Upload Word List Function
We wanted to add a bit more fun to the game, so we included a feature to upload your own word list. When you use the upload_word_list()
function, it opens a file dialog so you can pick a .txt
file with your list of words. If you don’t select a file, no worries—the game will just use the default list. But if you do upload a file, it reads through the list, splits it into individual words, and checks if the file is empty. If it’s empty, you’ll get an error message.
Otherwise, it swaps out the default word list for your new one and restarts the game to use your words. Plus, it lets you know if the upload was a success or if there were any hiccups along the way. If you forget to select a file, it’ll remind you to choose one.
def upload_word_list():
"""Allow user to upload a custom word list."""
global word_list, word
file_path = filedialog.askopenfilename(filetypes=[("Text Files", "*.txt")])
if file_path:
try:
with open(file_path, 'r') as file:
words = file.read().splitlines()
if words:
word_list = words
restart_game() # Start a new game with the uploaded word list
messagebox.showinfo("Word List Uploaded", "A new word list has been successfully uploaded.")
else:
messagebox.showerror("Error", "The file is empty.")
except Exception as e:
messagebox.showerror("Error", f"Failed to load the file: {e}")
else:
messagebox.showwarning("No File Selected", "Please select a valid text file.")
Game Setup and Initialization
Since we’ve covered how to upload a custom word list, let’s talk about the default setup for the game:
Initializing the Word List: First, we define the word_list
variable with a set of pre-selected words. This list includes terms like ‘python’, ‘hangman’, and ‘algorithm’ which will be used to randomly select the word to guess.
word_list = [
'python', 'hangman', 'programming', 'developer', 'algorithm', 'function',
'variable', 'software', 'debugging', 'network', 'database', 'compiler'
]
Selecting a Random Word: Next, we use random.choice()
to pick a random word from the word_list
and assign it to the word
variable. This is the word that players will try to guess during the game.
word = random.choice(word_list)
Initializing Guessed Letters: Following that, we create an empty set called guessed_letters
. This set will store all the letters that the player has guessed so far.
guessed_letters = set()
Setting the Number of Attempts: Finally, we initialize the attempts
variable to 6. This defines how many incorrect guesses the player is allowed before the game is over.
attempts = 6
Once that is set up, we begin by creating the graphical interface using tk
. We set its title and define its geometry. Next, we add a label that displays the hidden word in underscores and uses the display_word()
function to show the guessed letters. We also add a second label to display the number of remaining attempts, updating it whenever attempts change.
We then create an entry box for entering guesses and a label to show messages about whether the guessed letter is correct. Following that, we add a “Show Hint” button that calls the show_hint()
function, an “Upload Word List” button for the upload_word_list()
function, and a “Restart” button that triggers the restart_game()
function.
# Create GUI
root = tk.Tk()
root.title("Word Guesser Game - The Pycodes")
root.geometry("400x500")
word_label = tk.Label(root, text=display_word(word, guessed_letters), font=('Helvetica', 20))
word_label.pack(pady=20)
attempts_label = tk.Label(root, text=f"Attempts left: {attempts}", font=('Helvetica', 14))
attempts_label.pack(pady=10)
guess_entry = tk.Entry(root, font=('Helvetica', 16), width=3)
guess_entry.pack(pady=10)
guess_entry.bind("<Return>", process_guess)
message_label = tk.Label(root, text="", font=('Helvetica', 14))
message_label.pack(pady=10)
hint_button = tk.Button(root, text="Show Hint", command=show_hint)
hint_button.pack(pady=5)
upload_button = tk.Button(root, text="Upload Word List", command=upload_word_list)
upload_button.pack(pady=5)
restart_button = tk.Button(root, text="Restart", command=restart_game, state=tk.DISABLED)
restart_button.pack(pady=20)
To wrap things up, we kick off the mainloop()
method, which keeps the main window open and responsive, so you can interact with the game smoothly.
root.mainloop()
Example
- The wordlist used in this example is sourced from this GitHub repository.
- If you want to use your own custom wordlist, check out this article for detailed instructions.
- You can further customize this code by adding clues as values in the
word_list
and creating a label to display these clues. This will make the game easier and more engaging.
To play the game, simply enter a letter into the input box and press Enter.
Full Code
import tkinter as tk
from tkinter import filedialog, messagebox
import random
def display_word(word, guessed_letters):
"""Display the word with unguessed letters as underscores."""
return " ".join([letter if letter in guessed_letters else '_' for letter in word])
def process_guess(event):
"""Process user input guess and update game state."""
global word, guessed_letters, attempts, word_label, attempts_label, message_label
guess = guess_entry.get().lower()
guess_entry.delete(0, tk.END)
if len(guess) != 1 or not guess.isalpha():
message_label.config(text="Please enter a valid letter.")
return
if guess in guessed_letters:
message_label.config(text=f"You already guessed '{guess}'.")
elif guess in word:
guessed_letters.add(guess)
message_label.config(text=f"Good job! '{guess}' is in the word.")
else:
attempts -= 1
message_label.config(text=f"Sorry, '{guess}' is not in the word.")
update_game_state()
def show_hint():
"""Reveal a random letter from the word as a hint."""
global word, guessed_letters, attempts, message_label
available_letters = [letter for letter in word if letter not in guessed_letters]
if available_letters:
hint_letter = random.choice(available_letters)
guessed_letters.add(hint_letter)
attempts -= 1
message_label.config(text=f"Hint: The letter '{hint_letter}' has been revealed!")
update_game_state()
else:
message_label.config(text="No more letters to reveal.")
def update_game_state():
"""Update the game display and check for win/loss conditions."""
global word, guessed_letters, attempts, word_label, attempts_label, message_label, guess_entry, hint_button, restart_button
word_label.config(text=display_word(word, guessed_letters))
attempts_label.config(text=f"Attempts left: {attempts}")
if all(letter in guessed_letters for letter in word):
message_label.config(text=f"Congratulations! You've guessed the word '{word}'.")
end_game()
elif attempts == 0:
word_label.config(text=word)
message_label.config(text=f"Game Over! The word was '{word}'.")
end_game()
def end_game():
"""Disable input and show restart button when the game ends."""
guess_entry.config(state=tk.DISABLED)
hint_button.config(state=tk.DISABLED)
restart_button.config(state=tk.NORMAL)
def restart_game():
"""Restart the game with a new random word."""
global word, guessed_letters, attempts, word_list
word = random.choice(word_list)
guessed_letters = set()
attempts = 6
word_label.config(text=display_word(word, guessed_letters))
attempts_label.config(text=f"Attempts left: {attempts}")
message_label.config(text="")
guess_entry.config(state=tk.NORMAL)
hint_button.config(state=tk.NORMAL)
restart_button.config(state=tk.DISABLED)
def upload_word_list():
"""Allow user to upload a custom word list."""
global word_list, word
file_path = filedialog.askopenfilename(filetypes=[("Text Files", "*.txt")])
if file_path:
try:
with open(file_path, 'r') as file:
words = file.read().splitlines()
if words:
word_list = words
restart_game() # Start a new game with the uploaded word list
messagebox.showinfo("Word List Uploaded", "A new word list has been successfully uploaded.")
else:
messagebox.showerror("Error", "The file is empty.")
except Exception as e:
messagebox.showerror("Error", f"Failed to load the file: {e}")
else:
messagebox.showwarning("No File Selected", "Please select a valid text file.")
# Initialize game variables
word_list = [
'python', 'hangman', 'programming', 'developer', 'algorithm', 'function',
'variable', 'software', 'debugging', 'network', 'database', 'compiler'
]
word = random.choice(word_list)
guessed_letters = set()
attempts = 6
# Create GUI
root = tk.Tk()
root.title("Word Guesser Game - The Pycodes")
root.geometry("400x500")
word_label = tk.Label(root, text=display_word(word, guessed_letters), font=('Helvetica', 20))
word_label.pack(pady=20)
attempts_label = tk.Label(root, text=f"Attempts left: {attempts}", font=('Helvetica', 14))
attempts_label.pack(pady=10)
guess_entry = tk.Entry(root, font=('Helvetica', 16), width=3)
guess_entry.pack(pady=10)
guess_entry.bind("<Return>", process_guess)
message_label = tk.Label(root, text="", font=('Helvetica', 14))
message_label.pack(pady=10)
hint_button = tk.Button(root, text="Show Hint", command=show_hint)
hint_button.pack(pady=5)
upload_button = tk.Button(root, text="Upload Word List", command=upload_word_list)
upload_button.pack(pady=5)
restart_button = tk.Button(root, text="Restart", command=restart_game, state=tk.DISABLED)
restart_button.pack(pady=20)
root.mainloop()
Happy Coding!