$34.99
1 Introduction
The word-guessing game Wordle has recently gained huge popularity, and despite being fairly simple, was recently sold to the New York Times for an undisclosed price “in the low seven figures”. Once a day, players have up to six attempts to guess a word. After each guess, players receive the following feedback:
• Letters from the guess that are in the answer and in the correct position are coloured green;
• Letters from the guess that are in the answer but not in the correct position are coloured yellow; and
• Letters from the guess that are not in the answer are coloured grey.
Figure 1 demonstrates a partially and fully completed game of Wordle, where the answer is ‘ulcer’.
(a) A partially completed game. (b) The game is solved in three guesses.
Figure 1: Guess letters are coloured according to the rules, and keyboard letters are coloured according to current known information.
In this assignment you will implement a modified text-based version of Wordle. CSSE7030 students will also implement a simple solver to assist the user in making guesses during the game.
You are required to implement a number of functions as per Section 5 of this document.
2 Getting Started
Download a1.zip from Blackboard — this archive contains the necessary files to start this assignment. Once extracted, the a1.zip archive will provide the following files:
a1.py This is the only file you will submit and is where you write your code. Do not make changes to any other files.
a1 support.py Do not modify or submit this file, it contains functions to help you implement your tasks. You do not need to read or understand the code itself, but you should read the docstrings in order to get an idea of how the functions work. This file also contains some constants that will be useful in your implementation. In addition to these, you are encouraged to create your own constants in a1.py where possible.
vocab.txt This is the file containing the entire vocabulary of valid guesses, including potential answers.
answers.txt This is a reduced version of vocab.txt, from which answers will be randomly chosen for each round. Separating answers from the greater vocabulary ensures all answers are commonly known words, while allowing players to guess uncommon words.
NOTE: You are not permitted to add any import statements to a1.py. Doing so will result in a deduction of up to 100% of your mark.
3 Gameplay
1. Enter a guess. Guesses must be 6 letters long and exist in the known vocabulary. After a valid guess is entered, all previous guesses should be displayed with their information, before the user is prompted for their next guess.
2. Enter either ‘k’ or ‘K’. After displaying the keyboard information (see Section 5.8), the user should be re-prompted for their guess.
3. Enter either ‘q’ or ‘Q’. The user is opting to quit the game, and the program should terminate.
4. Enter either ‘h’ or ‘H’. The help message “Ah, you need help? Unfortunate.” should be printed, and the user should be re-prompted for their guess.
5. CSSE7030 students only: Enter either ‘a’ or ‘A’ to have the solver make the next guess. See Section 6 for more details.
If the user does not enter input that matches any of the above cases, it is assumed they have entered an invalid guess. In this case, the user should be informed of the way in which their guess is invalid (see Fig. 2 for the exact text you must match), before being reprompted for their guess.
The user continues until either:
• They win the round by guessing the word correctly within 6 guesses.
• They lose the round by entering 6 consecutive non-winning guesses.
• They quit the game by entering ‘q’ or ‘Q’.
At the end of a round, the user is informed of their outcome, along with their stats, before being prompted for whether they would like to play again. At this prompt, the user can either:
1. Enter either ‘y’ or ‘Y’ to play another round, in which case another word is chosen from the answers and another round commences with this new answer. You must not select the same word twice.
2. Enter anything else, in which case the game ends and the program terminates.
Figure 2 shows example gameplay for a fully functioning CSSE1001 Assignment 1. Here, the user opts to play two rounds, and then quit. If they had lost a round, the lose text should read “You lose! The answer was: {answer}” with the correct answer substituted for {answer}. If you have correctly handled the random selection of answer words, you should have the same first two answer words, and be able to replicate this output exactly. You should also test your program with other inputs.
4 Valid and invalid assumptions
In implementing your solution, you can assume that:
• All words (answers and full vocabulary) have exactly six letters. Any guess that does not contain exactly six letters is invalid.
• All answers will consist of six unique letters. No duplicate letters appear in answers.
• Your program will not be tested with guesses containing uppercase letters.
• A guess is valid if it is present in vocab.txt.
• Your program will not be tested for more rounds than there are available answers.
You must not assume that:
• Guesses will only be valid 6 letter words. Your program will be tested with invalid words, such as those containing special characters (e.g. non-letter characters) and words of incorrect length. These situations must be handled as specified in Section 3.
Figure 2: Basic gameplay demonstration. Blue text is program output. Black text is user input.
5 Implementation
Each function is accompanied with some examples for usage to help you start your own testing. You should also test your functions with other values to ensure they operate according to the descriptions.
Also note: IDLE 3.9 will not run a solution to this assignment. If you are using IDLE to develop you should use IDLE 3.10.
5.1 has won(guess: str, answer: str) -> bool
Returns True if the guess guess matches answer exactly. Otherwise, returns False. Precondition: len(guess) == 6 and len(answer) == 6
5.1.1 Example usage
5.2 has lost(guess number: int) -> bool
Returns True if the number of guesses that have occurred, guess number, is equal to or greater than the maximum number of allowed guesses (in our case, six). Otherwise, returns False.
5.2.1 Example usage
5.3 remove word(words: tuple[str, ...], word: str) -> tuple[str, ...]
Returns a copy of words with word removed, assuming that words contains word exactly once.
5.3.1 Example usage
5.4 prompt user(guess number: int, words: tuple[str, ...]) -> str
Prompts the user for the next guess, reprompting until either a valid guess is entered, or a selection for help, keyboard, or quit is made. Returns the first valid guess or request for help, keyboard, or quit. Note that the processing of the guess once it has been entered does not need to be handled in this function; it will be handled in functions defined later in this section. The returned string must be lowercase.
5.4.1 Example usage
5.5 process guess(guess: str, answer: str) -> str
Returns a modified representation of guess, in which each letter is replaced by:
• A green square if that letter occurs in the same position in answer; • A yellow square if that letter occurs in a different position in answer; or
• A black square if that letter does not occur in answer.
1. If one of the occurrences is in the correct position, it receives a green square and all other occurrences receive a black square.
2. Otherwise, if no occurrences are in the correct position, the first occurrence of the letter in guess receives a yellow square and all other occurrences receive a black square.
Precondition: len(guess) == 6 and len(answer) == 6
See a1 support.py for constants containing the required square characters.
5.5.1 Example usage
5.6 update history( history: tuple[tuple[str, str], ...], guess: str, answer: str ) -> tuple[tuple[str, str], ...]
Returns a copy of history updated to include the latest guess and its processed form. See Section 5.7 for example usage of this function. history is a tuple where each element is a tuple of (guess, processed guess).
5.7 print history(history: tuple[tuple[str, str], ...]) -> None
Prints the guess history in a user-friendly way.
5.7.1 Example usage
5.8 print keyboard(history: tuple[tuple[str, str], ...]) -> None
Prints the keyboard in a user-friendly way with the information currently known about each letter. Note that the two columns are tab-separated.
5.8.1 Example usage
5.9 print stats(stats: tuple[int, ...]) -> None
stats is a tuple containing seven elements, which are the number of rounds won in 1-6 guesses, and the number of rounds lost, respectively. This function prints the stats in a user-friendly way.
5.9.1 Example usage
5.10 main function
The main function should be called when the file is run, and coordinates the overall gameplay. The main function should be fairly short, and should utilize other functions you have written. In order to make the main function shorter, you should consider writing extra helper functions. In the provided a1.py, the function definition for main has already been provided, and the if name == main : block will ensure that the code in the main function is run when your a1.py file is run. Do not call your main function (or any other functions) outside of this block. The output from your main function (including prompts) must exactly match the expected output. Running the sample tests will give you a good idea of whether your prompts and other outputs are correct. See Figure 2 for example usage.
6 CSSE7030 Task
CSSE7030 student must also add a solver to the Wordle game. At the prompt for a guess, if a user enter ‘A’ or ‘a’, your solver should assist them by making the next guess. The word chosen for the guess must not violate any known information from previous guesses (e.g. if it is known that a letter exists in a position, the guess must have that letter in that position).
Figure 3 shows the added functionality during gameplay.
The design of the solver is up to you, but you must implement the following function, which should be called in your main function to handle the case where the user enters an ‘A’ or ‘a’:
6.1 guess next( vocab: tuple[str, ...], history: tuple[tuple[str, str], ...] ) -> Optional[str]
Returns a valid next guess that doesn’t violate known information from previous guesses. If no valid word remains in the vocabulary, this function should return None.
6.1.1 Example usage
Note that while our implementation has guessed the word ‘daines’, other words, such as ‘dancer’ could be valid guesses in this situation. A word such as ‘crayon’ would be an invalid guess in this instance for each of the following reasons:
1. We know from the first guess that there is no ‘y’ or ‘o’ in the answer.
2. We know from the first guess that the ‘n’ in the word does not appear in the last position.
3. We know from the second guess that there must be an ‘e’ anywhere other than the second position.
7 Assessment and Marking Criteria
This assignment assesses course learning objectives:
1. apply program constructs such as variables, selection, iteration and sub-routines,
2. read and analyse code written by others,
3. read and analyse a design and be able to translate the design into a working program, and
4. apply techniques for testing and debugging.
7.1 Functionality
7.2 Code Style
The key consideration in marking your code style is whether the code is easy to understand. There are several aspects of code style that contribute to how easy it is to understand code. In this assignment, your code style will be assessed against the following criteria.
• Readability
– Program Structure: Layout of code makes it easy to read and follow its logic. This includes using whitespace to highlight blocks of logic.
– Descriptive Identifier Names: Variable, constant, and function names clearly describe what they represent in the programs logic. Do not use Hungarian Notation for identifiers. In short, this means do not include the identifiers type in its name, rather make the name meaningful (e.g. employee identifier).
– Named Constants: Any non-trivial fixed value (literal constant) in the code is represented by a descriptive named constant (identifier).
• Algorithmic Logic
– Single Instance of Logic: Blocks of code should not be duplicated in your program. Any code that needs to be used multiple times should be implemented as a function.
– Variable Scope: Variables should be declared locally in the function in which they are needed. Global variables should not be used.
– Control Structures: Logic is structured simply and clearly through good use of control structures (e.g. loops and conditional statements).
• Documentation:
– Comment Clarity: Comments provide meaningful descriptions of the code. They should not repeat what is already obvious by reading the code (e.g. # Setting variable to 0). Comments should not be verbose or excessive, as this can make it difficult to follow the code.
– Informative Docstrings: Every function should have a docstring that summarises its purpose. This includes describing parameters and return values (including type information) so that others can understand how to use the function correctly.
7.3 Assignment Submission
You must submit your assignment electronically via Gradescope (https://gradescope.com/). You must use your UQ email address which is based on your student number (e.g. s4123456@student.uq.edu.au) as your Gradescope submission account.
When you upload your assignment it will run a subset of the functionality autograder tests on your submission. It will show you the results of these tests. It is your responsibility to ensure that your uploaded assignment file runs and that it passes the tests you expect it to pass.
7.5 Changelog