2 files in total
wordle.py
A PDF that contains your self-assessment & reflection
Log in to Coding Rooms
Navigate to the Assignment of Project 2: Wordle
Work through each part of the project and use Coding Rooms to develop your code.
When you're ready to submit, download the 1 file for Gradescope.
Review the solutions to perform a self-assessment and write your reflection.
You may write up your self-assessment and reflection in whatever format is most comfortable for you (written on paper, typed in a Word or Google Doc, etc.), but you must convert it to a PDF before submitting. Please ask if you need help with this!
Submit the PDF to Gradescope and name it SelfAssessmentReflection.pdf.
Homeworks are an opportunity to engage with the material and practice your programming skills. To support you, solutions will be available on moodle. It is your responsibility to engage with them in a way that strategically moves your learning forward. You should:
Attempt the homework without looking at the solutions.
Review the solutions; if you were stuck, you may revise your homework. You may find yourself iteratively reviewing and revising to best support your learning.
When you submit your homework, you will be required to complete a self-assessment and reflection:
Give yourself an assessment mark on the initial attempt:
✘ if you did not complete it
✓- if you completed it, but were very far from the solution
✓ if you completed it and essentially had the solution
✓+ if you completed it correctly, including precise communication
? if you are unsure as to whether or not you completed it
Provide a short reflection as to why you earned that mark, such as:
I did not understand how to get started, and it was too close to the deadline to visit support hours.
I got stumped by a bug where my program entered an infinite loop.
If you used the solutions to revise your work, describe what you needed to change, as in:
I modified the style of my conditional when I saw a simpler approach in the solutions.
I was so stuck that the majority of my submission is based on the solutions.
Ask specific questions on portions that are still confusing, such as:
Why does it cause an error when I returned "1" instead of 1?
[Optional] Provide one hint for the homework (to your past self or future student).
Wordle is a word-guessing game where players have 6 attempts to guess a hidden word. The word is 5 letters long, and each guess from the player must be a valid 5-letter word. If the player does not guess the word, they receive a clue.
The clue gives information for each of the guessed word's letters, which could be:
the correct letter in the correct spot -- we'll display a ♥
a correct letter in the word, but not in the correct spot -- we'll display a ♡
a letter not in the word at all -- we'll display a _
There are some sample executions of the game below to help you understand how the game play should unfold.
Click here to play the game and get more familiar with it!
ROUND 1!
What is your guess? sloth
sloth
____♡
ROUND 2!
What is your guess? heart
heart
♡_♥♡_
ROUND 3!
What is your guess? chair
chair
♥♥♥♥♥
Yes, the word was chair!
Congratulations, you won!
ROUND 1!
What is your guess? blank
blank
___♡_
ROUND 2!
What is your guess? noise
noise
♡_♡♡♥
ROUND 3!
What is your guess? snipe
snipe
♥♡♡_♥
ROUND 4!
What is your guess? swine
swine
♥_♡♡♥
ROUND 5!
What is your guess? singe
singe
♥♥♥_♥
ROUND 6!
What is your guess? smile
smile
♥_♡_♥
The word was since.
Too bad, you lost.
ROUND 1!
What is your guess? blink
blink
__♡♡_
ROUND 2!
What is your guess? night
night
♡♥___
ROUND 3!
What is your guess? sink
.....
_____
ROUND 4!
What is your guess? diner
diner
♡♥♥__
ROUND 5!
What is your guess? windy
windy
♥♥♥♥♥
Yes, the word was windy!
Congratulations, you won!
As with your first project, the instructions will walk you through a design. You'll continue practicing:
writing function definitions from high-level descriptions
type-hinting and using mypy to make sure types are consistent
the iterative process of writing a little code, running your program and debugging
Be strategic!
As a project:
You will not have access to solutions for this project.
The Gradescope autograder will not reveal the tests for your project.
This is because it is important for you to understand how to test your code.
Be intentional around your approach to working on the project:
Start early!
Ask questions!
Leave time for questions by... starting early :)
When you're stuck, pause and evaluate what could be going on. Remember the self-regulated learning cycle!
Do you have a plan?
Are you evaluating your plan? How will you test your code as you go?
How will you revise? What will you do when you're confused? Stuck?
Resist the temptation to write the entire program all at once! Otherwise, the debugging process becomes so much more difficult and time-consuming!
First, create the skeleton of your program by writing function "stubs"; run mypy to check types, then make sure your program runs without errors.
Then implement one function and test it in isolation. You have seen guidance for this throughout the class (refer back to examples, homeworks and the project).
Have pen and paper with you to diagram memory, particularly for the functions where you are determining the clue. Make sure you understand the expected behavior on paper before trying to implement them.
Work examples! What do you expect the parameters to be? What do you expect the result to be?
Test your code with these examples by writing small test functions. You should leave these in your program to help us understand your process. If you want some examples, look back at the buggy programs from HW 3: Animations and HW 4: ConditionOwls.
Remember the debugging strategies:
Print statements help you peek at memory during program execution.
Tracing your program on paper helps you understand when the execution doesn't match your intended logic.
The following "call graph" shows how the functions relate to each other.
An arrow indicates an invocation.
For example playWordle invokes the readFileToList function 2 times.
The pink "cloud" highlights the part of the design that is focused on creating the clue and calls attention to 3 lists that are used to help with this.
Use the following design to create your function stubs then implement them individually.
Not all functions have pseudocode for how to implement the expected behavior. For these, make sure you write pseudocode first, which should become a comment in the code.
Some functions do have pseudocode for how to implement the expected behavior. For these, you should copy/paste the pseudocode and keep it as a comment. This is good style and will help as you are debugging.
As with other designs, the order of the functions does not matter.
Expects one parameter of type list
Returns a str
Choose a word randomly from the passed list and return it.
As you build up your program, you may want to "hard-code" the secret word. You can do this by commenting out the correct implementation and putting the hard-coded word instead, as in:
return "knoll"
Expects two parameters:
word of type str
validWords of type list
Returns a bool
Returns True if the given word is in the list of valid words.
Expects a single parameter filePath of type str
Returns a list
Given a path to a file with a word on each line, read the file and return a list with each word as an element.
You did this in Lab 6: Sparkles! The solutions are available on moodle.
Expects no parameters
Returns a bool
Main game function that allows a user to interactively play the game. Returns True when the user wins and False when the user loses.
Pseudocode for how (you can also try to write this on your own!)
read the common words list from "common5.txt" -- this is where the hidden words are pulled from
read the valid words list from "scrabble5.txt" -- this is the list to check a user's guess against
choose a hidden 5-letter word from the common words list
play (at most) 6 rounds
print the round number, as in
ROUND 1!
play a round to see if they won
if they won
print that they guessed the hidden word, as in
Yes, the word was chair!
return True to end the function's execution (which also stops the loop)
when all 6 iterations of the loop execute, then the game was not won within 6 guesses, so...
print the hidden word, as in
The word was since.
return False to indicate the player lost
Expects 2 parameters:
hiddenWord of type str
validWords of type list
returns a bool
Given the hiddenWord and list of validWords, play a round of the game. Prompt the user for their guess. If the user enters an invalid word, then "....." is substituted as a default. Returns True if they guessed the hiddenWord and False otherwise.
How? You'll need to use the isValidWord function, the createClue function (described below) and the gameWon function.
Expects 1 parameter clue of type str
Returns a bool
Given a clue, check if the game has been won; return True if it has, False otherwise.
Assumes index i is
"♥" if the letter is in the word and in that spot
"♡" if the letter is in the word, but not in that spot
"_" if the letter is not in the word
How? Check if the string is all "♥"
Expects no parameters
Returns None (or you can omit the return type)
Play Wordle and print out whether the user has won/lost
If they win, print:
Congratulations, you won!
Otherwise, print:
Too bad, you lost.
Creating the clue requires a bit of logic, which we worked on in class.
At first thought, we might think this simple approach would work:
for each letter of the guess
if the letter is correct (in the word at that spot)
put a ♥
otherwise if the letter is in the word (and not in that spot)
put a ♡
otherwise (the letter is not in the word)
put a _
However, this fails for the following example:
the hidden word is "crate"
the player guesses "sweep"
the approach above would result in "__♡♡_"
which incorrectly leads the player to believe there are two "e"s in the word, when there is only one.
The design below solves this by matching letters and essentially crossing them off by clearing them out of (copies of) the guess and hidden word.
Expects 2 parameters:
hiddenWord of type str
guess of type str
Returns a str
Given a hidden word and a guess (both length 5), create and return a clue that is a string of length 5 where index i is
"♥" if the letter is in the word and in that spot
"♡" if the letter is in the word, but not in that spot
"_" if the letter is not in the word
Pseudocode for how
We'll use a list to build the clue and convert it to a string at the end of the function; this is because we want to change the list entries during the function body (strings are immutable)
Initialize a clueList variable of type list to hold 5 "?" values (this will help us know which entries we haven't finalized)
In order to build the clue, we'll need to match letter's in the player's guess against letters in the hidden word. We'll do this by maintaining two lists.
We will track the unmatched letters of the hidden word
Initialize a unmatchedHiddenLetters variable of type list to the letters of the hiddenWord by using the function list.
This is not something we've seen before, so here is the code:
unmatchedHiddenLetters:list = list(hiddenWord)
We will track the unmatched letters of the guess,
Initialize it to the user's guess using the list function as above.
First, update the three lists to reflect completely right/wrong guess values by invoking updateClueForRightAndWrong
Then, update the lists to match guessed letters in the hidden word (not yet matched) with the first occurrence in the guess by invoking updateClueForPartialMatches
Finally, clear out the unmatched guess letters (these are additional occurrences of letters in the hidden word) by invoking updateClueForMismatches
Collapse the clue back to a string using the join method
clueAsString:str = "".join(clue)
return the clue
Expects 3 parameters:
clue of type list
unmatchedHiddenLetters of type list
unmatchedGuessLetters of type list
Has a return type of None
Assumes clue is a list with all "?" values,
unmatchedHiddenLetters has the letters of the hidden word (none are matched yet) and
unmatchedGuessLetters has the letters of the guess word (none are matched yet).
Updates the lists, so that
- clue at index i is "♥" (correct match in the correct spot),
"_" (letter is not in the hidden word at all)
"?" otherwise
- unmatchedHiddenLetters at index i is "" for any correct match in the correct spot
- unmatchedGuessLetters at index i is "" for any correct match in the correct spot
For example, given ["?","?","?","?","?"], ["b","l","o","c","k"], ["k","n","o","l","l"], the lists should update to ["?","_","♥","?","?"], ["b","l", "","c","k"], ["k","n","","l","l"] because index 1 ("n") is completely wrong, index 2 ("o") is completely right, and the remaining indices 0,3, and 4 are partial matches (the letter's "k" and "l" are in the word but not in those indices).
Pseudocode for how
Walk the guess letters and hidden letters in parallel by looping over the index values 0,...,4
If there is a match (correct letter in the correct spot)
update the clue to be a "♥"
update the remainingHiddenLetters and remainingGuessLetters lists to both hold ""
("clear out" the letter from consideration)
Otherwise if the letter is not matchable (which is when it is not in the list of unmatched hidden letters)
update the clue to be a "_"
Expects 3 parameters:
clue:list, unmatchedHiddenLetters:list, unmatchedGuessLetters:list ) -> None:
Assumes the following about the lists:
- clue at index i is "♥" (correct match in the correct spot),
"_" (letter is not in the hidden word at all)
"?" otherwise
- unmatchedHiddenLetters at index i is "" for any correct match in the correct spot
- unmatchedGuessLetters at index i is "" for any correct match in the correct spot
Updates the lists to match guessed letters in the hidden word (not yet matched) with the first occurrence in the guess. Any unmatched guess letters remain "?".
For example, given ["?","_","♥","?","?"], ["b","l", "","c","k"], ["k","n","","l","l"], the lists should update to ["♡","_","♥","♡","?"], ["b", "", "","c", ""], [ "","n","", "","l"] because two partial matches are found - the l is matched to the first guessed l (in index 4) and the k is matched to the (only) guessed k.
Pseudocode for how:
iterate over the hidden letters to find partial matches
if it's a real letter (not "") and it's a letter that was guessed (but wasn't matched)
i.e., if it's not "" and it is in the remainingGuessLetters list
find the index of the first occurrence in the unmatched guess letters (here is the code, since you may not be familiar with the string method index):
firstIndex:int = unmatchedGuessLetters.index( hiddenLetter )
update the clue to have a "♡" there
update the unmatchedGuessLetters to "" since we've matched it
Expects a single paramter called clue of type list
Has a return type of None
Change all "?" to "_"