Build a Terminal Wordle Clone in Python
Build a playable Wordle clone in Python using only core programming fundamentals.
Introduction
30 Second Summary
AI can write code for you in seconds. But the ability to reason through a problem, break it into pieces, and translate your thinking into working logic is a muscle. If you stop using it, it atrophies.
In this project, you will build a fully playable Wordle clone in your terminal using Python. You will write every line from an empty file, reasoning through each problem before coding the solution.
What You'll Build
You will run your game in the terminal, type a 5-letter guess, and instantly see colored letter-by-letter feedback telling you exactly which letters are correct, misplaced, or absent.
By the end of this project, you'll have:
- A playable terminal Wordle game where you type a guess and see each letter light up in green, yellow, or grey based on how close you are to the answer.
- A two-pass comparison algorithm that correctly handles duplicate letters, the trickiest logic problem in the game.
- Working knowledge of variables, conditionals, loops, functions, and lists that you built by doing, not by watching or prompting.
- Secret Mission: Add a real word list so the game rejects nonsense guesses and only accepts actual English words.
Are there any prerequisites?
None. This project includes setup verification for Python and VS Code in Step 1. If you have a Mac with a code editor installed, you are ready to start.
Before We Start
Before we dive in, let's lock in what you're about to build and why you're building it by hand. This project is about rebuilding the muscle to think through code yourself, one line at a time.
Verify Your Tools
Before writing any code, you need to confirm that Python runs on your machine and that your editor can create and run a file.
One wrong version or missing path can waste 30 minutes debugging the wrong thing. In this step, you will verify both tools are ready so you can focus entirely on building your game.
In this step, get ready to:
- Confirm Python 3 is installed and working in Terminal.
- Create and run a test file in VS Code (or Cursor).
Confirm Python is installed
Your Mac needs Python installed so you can run the game you are about to write. The quickest way to check is to ask Python for its version number.
- Press Cmd+Space to open Spotlight search.
- Type Terminal and press Enter to open it.
- Check your Python version by running this command:
python3 --version
What do you see in your terminal?
✔️ I see a version number starting with 3
Python is ready to go. Any version starting with 3 (such as Python 3.14.6) works for this project.
ⓧ Command not found
Python 3 is not installed on your machine yet.
- Download the latest Python 3 installer from python.org/downloads.
- Open the downloaded .pkg file and follow the installation prompts.
- Close and reopen Terminal.
- Run python3 --version again. You should now see a version starting with 3.
Create and run your first file
Now you need to confirm your code editor can create a Python file and run it. This proves the full loop works: write code, save, run, see output.
- Press Cmd+Space to open Spotlight search.
- Type VS Code (or Cursor if that is your editor) and press Enter to open it.
- Open the integrated terminal by pressing Ctrl+` (the backtick key above Tab).
- Move to your Desktop by running this command:
cd ~/Desktop
- Create your project folder and move into it by running these commands:
mkdir wordle
cd wordle
- Confirm the folder exists by running:
ls ~/Desktop
You should see wordle listed in the output.
- Open this folder in your editor by running:
code .
Using Cursor instead?
Run cursor . instead of code . to open the folder in Cursor.
Your editor reopens with the wordle folder as the workspace.
- In the Explorer sidebar on the left, click the New File icon (a page with a plus sign).
- Name the file wordle.py and press Enter.
- Type the following code into wordle.py:
print("hello")
- Save the file by pressing Cmd+S.
Before you run this, what do you expect to see in the terminal?
- In the integrated terminal, run your file with this command:
python3 wordle.py
You should see hello printed in the terminal. That confirms your editor, Python, and your project folder all work together.
Don't see hello?
- Make sure you saved the file (Cmd+S). Unsaved changes will not run.
- Check that your terminal is in the wordle folder. Run pwd to see your current directory.
- Confirm the file is named exactly wordle.py (not wordle.py.txt or similar).
Still stuck? Help me debug why python3 wordle.py is not printing hello
✔️ Awesome, I've got everything!
Great. Make sure you have saved wordle.py and you are ready to move on.
ⓧ I'd like to double check the full code
Your wordle.py should contain exactly this:
print("hello")
Your toolchain is confirmed working. Next up, you will store a secret word and get the player's first guess.
Store a Word and Get a Guess
Your tools are ready. Now it is time to write actual game logic.
Every program starts with data (something to work with) and input (something from the user). Right now wordle.py just prints "hello" and exits. You need a secret word stored somewhere and a way to capture what the player types. That gives you the baby version of Wordle: type a word, see if it matches.
In this step, get ready to:
- Store a secret word in a variable.
- Capture the player's guess using input.
- Compare the guess to the secret word with a conditional.
Write the game logic
You need two pieces of data: a secret word the player is trying to guess, and the guess itself captured from their keyboard. Then a conditional decides whether they win or lose.
- Switch back to wordle.py in VS Code.
- Delete the print("hello") line so the file is completely empty.
- Type the following code into the empty file:
# Store the answer the player is trying to guess
secret_word = "crane"
# Ask the player to type a word and store their response
guess = input("Enter your guess: ")
# Check if the guess matches the secret word
if guess == secret_word:
print("You win!")
else:
print("Wrong!")
What does this code do?
- secret_word = "crane" creates a variable that holds the answer. A variable is a name that points to a piece of data so you can use it later.
- input("Enter your guess: ") pauses the program and waits for the player to type something. Whatever they type gets stored in the guess variable.
- if/else is a conditional. It checks whether two values are equal (==) and runs different code depending on the answer.
- Save wordle.py.
Before you run this, think: what do you expect to happen when you type "crane"? What about when you type something else?
- Run the program in your integrated terminal by entering this command:
python3 wordle.py
- When it asks for your guess, type crane and press Enter.
You should see You win! printed below your guess.
- Run it again with the same command:
python3 wordle.py
- This time, type any other word (like slate) and press Enter.
You should see Wrong! printed instead. The conditional did its job.
Seeing a SyntaxError or nothing happens?
- Check that your if and else lines end with a colon (:). Missing colons are the most common Python syntax error.
- Make sure the print lines are indented with 4 spaces under the if and else. Python uses indentation to know which code belongs inside a block.
- Confirm you deleted the old print("hello") line. If it is still there, the file may not run as expected.
Why is my wordle.py throwing a SyntaxError?
✔️ Awesome, I've got everything!
Great. Double check you have saved wordle.py and both tests (correct word and wrong word) gave you the expected output.
ⓧ I'd like to double check the full code
Here is the complete wordle.py at this point. Make sure yours matches exactly:
secret_word = "crane"
guess = input("Enter your guess: ")
if guess == secret_word:
print("You win!")
else:
print("Wrong!")
Your program can tell right from wrong. But one guess and the game is over. Next up, you will give the player 6 chances to crack the code.
Give the Player 6 Tries
Your game works, but it ends after a single guess. Real Wordle gives you 6 attempts to find the word.
You need a loop that repeats the guessing process and a way to stop early if the player wins. Think about: what repeats, what stops the repetition, and what changes each time through.
In this step, get ready to:
- Wrap the input and conditional in a for loop that runs 6 times.
- Track the attempt number and display it on a win.
- Print the secret word if all 6 guesses are wrong.
Wrap the game logic in a loop
A for loop repeats a block of code a fixed number of times. You need your input prompt and conditional check to repeat 6 times, and you need a way to stop the loop early when the player guesses correctly.
- In VS Code, select all the code in wordle.py and delete it.
- Replace it with the following code:
secret_word = "crane"
# Track whether the player has won
won = False
# Give the player 6 attempts
for attempt in range(6):
guess = input(f"Attempt {attempt + 1}/6: ")
if guess == secret_word:
print(f"You win! You got it in {attempt + 1} attempt(s)!")
won = True
break
else:
print("Wrong!")
# If the loop ended without a win, reveal the answer
if not won:
print(f"Game over! The word was: {secret_word.upper()}")
What does this code do?
- won = False creates a flag that starts as False. If the player guesses correctly, it flips to True.
- for attempt in range(6) runs the indented code 6 times. The variable attempt counts from 0 to 5 automatically.
- The f-string f"Attempt {attempt + 1}/6: " shows the human-friendly attempt number (1 through 6 instead of 0 through 5).
- break exits the loop immediately when the player wins. Without it, the game would keep asking for guesses even after a correct answer.
- The if not won check after the loop only runs if the player never flipped won to True. It reveals the secret word.
Before you run this, think: what will happen if you type a wrong word 6 times in a row? What should appear after the 6th wrong guess?
- Save wordle.py.
- Run the game in your integrated terminal:
python3 wordle.py
Type any wrong word 6 times. After the 6th wrong guess, you see the game over message with the secret word revealed in capitals.
- Run it again. This time, type crane on your second or third attempt.
You see a win message that tells you which attempt you got it on, and the game stops immediately.
Game not stopping after a correct guess?
- Make sure break is inside the if guess == secret_word block, indented to the same level as print and won = True.
- Check that you have won = True before the break line. If won never flips, the game over message prints even after a win.
- If you see IndentationError, make sure all lines inside the for loop use exactly 4 spaces of indentation.
Why is my game printing the wrong attempt number or not stopping?
✔️ Awesome, I've got everything!
Great. Double check you have saved wordle.py and your game handles both winning and losing correctly.
ⓧ I'd like to double check the full code
secret_word = "crane"
won = False
for attempt in range(6):
guess = input(f"Attempt {attempt + 1}/6: ")
if guess == secret_word:
print(f"You win! You got it in {attempt + 1} attempt(s)!")
won = True
break
else:
print("Wrong!")
if not won:
print(f"Game over! The word was: {secret_word.upper()}")
Your game now plays like real Wordle. Six chances, a clear win message, and the answer revealed on failure. Next up, you will add the colored letter-by-letter feedback that makes Wordle actually useful.
Show Letter-by-Letter Feedback
Right now, your game only tells the player "Wrong!" for the entire word. That is useless feedback. Wordle's core mechanic is showing which individual letters are correct, misplaced, or absent.
In this step, you'll write a function that compares two strings character by character and decides a color for each position. Green means right letter, right spot. Yellow means right letter, wrong spot. Grey means the letter is not in the word at all.
In this step, get ready to:
- Write a function that checks each letter and assigns a color.
- Display colored letter-by-letter feedback in the terminal using ANSI codes.
- Wire the feedback into your game loop.
Write the check_guess function
You need a function that takes a guess and the secret word, then returns a list of color labels for each letter position. The logic compares each character at index i in both strings.
- In wordle.py, find the line won = False. Add the following function below it, above the for loop:
def check_guess(guess, secret_word):
# Compare each letter and build a list of color labels
result = []
for i in range(5):
if guess[i] == secret_word[i]:
result.append("green")
elif guess[i] in secret_word:
result.append("yellow")
else:
result.append("grey")
return result
What does this code do?
The function loops through positions 0 to 4 (five letters) and makes a decision for each:
- If the letter at position i matches exactly, it appends "green".
- If the letter exists somewhere in the secret word (but not at this position), it appends "yellow".
- Otherwise, the letter is not in the word at all, so it appends "grey".
- Save wordle.py. The function is not called yet, so you will not see output. The next chunk puts it to use.
Define ANSI color constants and write display_result
Terminals can display colored text using special escape sequences called ANSI codes. You wrap a piece of text between a color code and a reset code, and the terminal renders it in that color.
- At the very top of wordle.py (line 1, above everything else), add these four color constants:
GREEN = "\033[92m"
YELLOW = "\033[93m"
GREY = "\033[90m"
RESET = "\033[0m"
What are these escape codes?
Each string starts with \033[ which tells the terminal "a color instruction follows." The number picks the color. \033[0m resets back to normal.
macOS Terminal supports these natively. No extra libraries needed.
- Now add the display_result function below your check_guess function, still above the for loop:
def display_result(guess, result):
# Build a string of colored letters and print it
output = ""
for i in range(5):
letter = guess[i].upper()
if result[i] == "green":
output += GREEN + letter + RESET
elif result[i] == "yellow":
output += YELLOW + letter + RESET
else:
output += GREY + letter + RESET
print(output)
What does display_result do?
It loops through each letter position, uppercases the letter, then wraps it in the matching color code based on the result list. The final string is one line of colored text that prints to the terminal.
- Save wordle.py. Both functions are defined but not called yet. The next substep wires them in.
Wire the functions into your game loop
Your two functions are ready. Now you need to call them inside the game loop so the player actually sees colored feedback.
- In wordle.py, scroll down to the for loop and find this block:
if guess == secret_word:
print(f"You win! You got it in {attempt + 1} attempt(s)!")
won = True
break
else:
print("Wrong!")
- Replace that entire block with the following code:
if guess == secret_word:
# Show all green on a correct guess
display_result(guess, ["green"] * 5)
print(f"You win! You got it in {attempt + 1} attempt(s)!")
won = True
break
# Check the guess and display colored feedback
result = check_guess(guess, secret_word)
display_result(guess, result)
What changed here?
- On a correct guess, display_result(guess, ["green"] * 5) shows all five letters in green before the win message.
- The else: print("Wrong!") is gone. Instead, every wrong guess runs through check_guess and display_result to show per-letter color feedback.
- Save wordle.py.
Before you run this, think about what you expect to see if you guess "trace" when the secret word is "crane". Which letters do you think will be green, yellow, or grey?
- Run your game by entering this command in the terminal:
python3 wordle.py
- Try guessing a word that shares some letters with the secret word (remember, the answer is crane). Try trace to see a mix of colors.
You should see each letter printed in a different color. Green letters are in the correct position. Yellow letters are in the word but the wrong spot. Grey letters are not in the word at all.
Not seeing any colors?
- Make sure the escape codes use a backslash followed by 033, not a zero-three-three typo. The backslash is critical.
- Check that RESET is defined as "\033[0m". Without the reset, colors bleed into all following text.
- Confirm you removed the old else: print("Wrong!") and replaced it with the check_guess and display_result calls.
Still stuck? Why isn't my terminal showing colored text in Python?
✔️ Awesome, I've got everything!
Great. Double check you have saved wordle.py and that your colored output matches what you expected.
ⓧ I'd like to double check the full code
Your wordle.py should now have these sections in this order. Scroll through your file and confirm each is present:
- Lines 1-4: The four ANSI color constants (GREEN, YELLOW, GREY, RESET).
- Then secret_word = "crane" and won = False.
- The check_guess function (takes guess and secret_word, returns a list of color strings).
- The display_result function (takes guess and result, prints colored letters).
- The for attempt in range(6) loop calling display_result on a win and calling both check_guess and display_result on a wrong guess.
- The if not won game-over message at the bottom.
Your game now gives real feedback on every guess. You can see exactly which letters are correct, which are in the wrong spot, and which are not in the word. Next up, you will fix a subtle bug hiding in this logic and add a few finishing touches.
Fix the Duplicate Letter Bug and Add Polish
Your Wordle game now shows colored feedback for each letter. There is a problem lurking in your algorithm though.
If the secret word is "crane" and you guess "creep", your code colors both "e" letters even though "crane" only has one "e". In this step, you will fix that bug, add input validation to reject bad guesses, and make the word random each time you play.
In this step, get ready to:
- Fix the duplicate letter bug with a two-pass algorithm.
- Add input validation to reject guesses that are not exactly 5 letters.
- Add random word selection so the answer changes each game.
Expose the duplicate letter bug
Before you fix anything, let's make the bug visible. The secret word is still hardcoded as crane, which has exactly one "e".
- Run your game by running this command:
python3 wordle.py
Before you type your guess, predict: if you guess "creep", how many letters do you think will be colored yellow or green for the letter "e"?
- Type creep as your guess and press Enter.
Both "e" letters get colored, even though "crane" only contains one "e". That is the bug. Your single-pass algorithm cannot tell that the first "e" already consumed the only available "e" in the secret word.
Rewrite check_guess with a two-pass algorithm
The fix uses two passes over the guess. The first pass locks in greens (exact matches) and marks those positions as used. The second pass only assigns yellows from the remaining unused letters.
- In wordle.py, find the entire check_guess function and replace it with this new version:
def check_guess(guess, secret_word):
result = ["grey"] * 5
remaining = list(secret_word)
# First pass: mark exact matches (greens)
for i in range(5):
if guess[i] == secret_word[i]:
result[i] = "green"
remaining[i] = None
# Second pass: mark misplaced letters (yellows)
for i in range(5):
if result[i] == "green":
continue
if guess[i] in remaining:
result[i] = "yellow"
remaining[remaining.index(guess[i])] = None
return result
What does this code do?
The function starts by assuming all letters are grey. It builds a remaining list from the secret word's characters to track which letters are still available.
The first loop finds exact matches and sets those positions to None in remaining so they cannot be claimed again. The second loop only assigns yellow if the letter still exists in remaining, and removes it after use. This ensures each letter in the secret word can only be matched once.
- Save wordle.py and run the game again:
python3 wordle.py
- Guess creep again. This time, only one "e" should be colored (the one in position 3 is green because it matches "crane" exactly). The second "e" stays grey.
Both e's still colored?
Make sure you replaced the entire old check_guess function, not just part of it. The new version starts with result = ["grey"] * 5 instead of result = [].
help me debug my check_guess function for duplicate letters
Add input validation and wrap the game in a function
Right now, typing "hi" or "12345" gets processed as a guess. You need an inner loop that keeps asking until the player enters exactly 5 alphabetical characters. While you are restructuring, you will wrap all the game logic in a play() function to keep things organized.
- In wordle.py, find and delete these lines that sit below your display_result function:
secret_word = "crane"
won = False
for attempt in range(6):
guess = input(f"Attempt {attempt + 1}/6: ")
if guess == secret_word:
display_result(guess, ["green"] * 5)
print(f"You win! You got it in {attempt + 1} attempt(s)!")
won = True
break
result = check_guess(guess, secret_word)
display_result(guess, result)
if not won:
print(f"Game over! The word was: {secret_word.upper()}")
- In the same spot (below display_result), add this play() function and its call:
def play():
secret_word = "crane"
won = False
print("WORDLE - Guess the 5-letter word! You have 6 attempts.\n")
for attempt in range(6):
# Inner loop keeps asking until input is valid
while True:
guess = input(f"Attempt {attempt + 1}/6: ").lower().strip()
if len(guess) != 5:
print("Your guess must be exactly 5 letters.")
continue
if not guess.isalpha():
print("Your guess must contain only letters.")
continue
break
if guess == secret_word:
display_result(guess, ["green"] * 5)
print(f"\nYou win! You got it in {attempt + 1} attempt(s)!")
won = True
break
result = check_guess(guess, secret_word)
display_result(guess, result)
if not won:
print(f"\nGame over! The word was: {secret_word.upper()}")
play()
What does this code do?
The while True loop inside the for loop is a validation gate. It re-prompts the player until they enter exactly 5 alphabetical characters. The continue jumps back to the top of the while loop (not the for loop), so invalid guesses never consume an attempt.
The .lower().strip() on the input normalizes the guess. Players can type "CRANE" or " crane " and the game handles it gracefully.
- Save wordle.py and run:
python3 wordle.py
- Try typing hi as a guess. You should see "Your guess must be exactly 5 letters." and get asked again without losing an attempt.
- Try typing 123ab. You should see "Your guess must contain only letters."
- Type crane to confirm the game still works and you see the win message.
Game crashes or skips validation?
Check that while True: is indented inside the for loop, and that the if guess == secret_word: block sits outside the while loop (at the same indent level as while True). The break at the end of the while block exits validation, not the game loop.
help me fix indentation in my play function validation loop
Add random word selection
The game always uses "crane" right now. Adding a word list and picking randomly makes each game different.
- At the very top of wordle.py (above the ANSI color constants), add this import and word list:
import random
GREEN = "\033[92m"
YELLOW = "\033[93m"
GREY = "\033[90m"
RESET = "\033[0m"
word_list = ["crane", "slate", "trace", "crate", "blaze", "gripe", "mount", "flesh", "vivid", "plumb"]
What does this code do?
The import random line brings in Python's built-in random module. The word_list stores 10 five-letter words the game can choose from. Having the list at module level means it is defined once and accessible inside any function.
- Inside your play() function, find this line:
secret_word = "crane"
- Replace it with:
secret_word = random.choice(word_list)
What does random.choice do?
The random.choice() function returns a random element from a non-empty sequence. Each time play() runs, it picks a different word from your list.
- Save wordle.py.
Before you run, predict: will the game still say "Attempt 1/6" as the first prompt, or has that changed?
- Run the game:
python3 wordle.py
- You should see the welcome message "WORDLE - Guess the 5-letter word! You have 6 attempts." followed by the first prompt. The prompt still shows "Attempt 1/6" because that has not changed.
- Use all 6 guesses (or press Ctrl+C to quit). Then run the game a second time. The game-over message should reveal a different word than the first run.
Same word every time?
Make sure you replaced secret_word = "crane" with secret_word = random.choice(word_list) inside the play() function. Also confirm that import random is at the very top of the file.
help me debug why my Wordle game picks the same word every time
✔️ Awesome, I've got everything!
Great. Double check you have saved wordle.py and all three improvements are working: duplicate letters handled, invalid input rejected, and a random word each game.
ⓧ I'd like to double check the full code
Scroll up through your file and confirm these sections are present, in this order:
- import random at the very top.
- The four ANSI color constants (GREEN, YELLOW, GREY, RESET).
- word_list with 10 five-letter words.
- check_guess with the two-pass algorithm (remaining list, first loop for greens, second loop for yellows).
- display_result unchanged from the previous step.
- play() function containing secret_word = random.choice(word_list), won = False, the welcome print, the for loop with the inner while True validation loop, win detection, and game-over message.
- play() called at the very bottom of the file.
Secret mission
Validate Guesses Against a Real Word List
Right now your game accepts any 5 random letters as a guess. Real Wordle only lets you submit actual English words. Can you add a word list file and teach your game to reject nonsense?
Clean Up Your Resources
Clean Up Your Resources
This project runs entirely locally, so there are no ongoing costs. Your files live on your machine and nothing is running in the background.
Resources you used:
- wordle.py file (your game code).
- words.txt file (your word list for the Secret Mission).
Keep everything running
No action needed. Choose this if you want to keep playing your Wordle game or keep building on it.
- Your wordle.py and words.txt files stay where they are.
- Python remains installed on your machine. You can use it for future projects.
- Run python3 wordle.py any time to play again.
Pause - I'll come back to this later
Since this is a local project with no running processes, there is nothing to pause. Your files will be waiting for you when you come back.
- Your files use negligible disk space. No action needed.
- When you return, open wordle.py in VS Code and run it in the integrated terminal.
Delete - I don't want to use this again
Remove your project files entirely. You can always rebuild from scratch using this guide.
- Delete your game files by running this command in Terminal from the directory that contains them:
rm wordle.py words.txt
- Confirm the files are gone by running:
ls
You should no longer see wordle.py or words.txt in the output.
Nice Work!
Nice Work!
You just wrote a complete, playable Wordle game from an empty file. Every line of logic in wordle.py exists because you reasoned through it yourself.
You've learned how to:
- Use variables to store state, conditionals to branch logic, loops to repeat actions, functions to organize code, and lists to track data.
- Solve a real algorithmic problem (letter-by-letter comparison with duplicate handling) by reasoning through it step by step.
- Build a complete program using only Python standard library features (random, ANSI color codes, string methods) with zero external dependencies.
- Secret Mission: Add file I/O and set-based validation to reject non-English guesses.
Ready to quiz yourself?