exercise7_template
1from cs110_ex7 import * 2from random import choice 3########################## CANVAS SETUP CODE ############################## 4# initialize window 5gui = Tk() 6gui.title("SUPER Wordle!") 7 8canvas = Canvas(gui,background="white") 9setup_window(canvas) 10 11# the next thing is a list of all the functions in this file. It"s so we can 12# generate that cool web version of the documentation. You don"t need to 13# worry about it. 14__all__ = [ 15 "get_difficulty", "read_in_words", "generate_hint", "finalize_guess", 16 "show_past_guess", "show_game_board", "handle_typing" 17] 18########################## GAMEPLAY FUNCTIONS ############################## 19 20# Dictionary to store all of the game data 21GAME_DATA = { 22 "solution": "", # a string that is the secret solution 23 "current_guess": "", # a string that contains the current guess 24 "past_guesses": [], # a list that contains all of the past guesses 25 "word_list": [], # a list that will contain all the valid n letter words 26 "num_letters": 5, # how many letters does each solution contain 27 } 28 29 30def get_difficulty(): 31 """ 32 Uses a pop-up window to ask the user to input the desired difficulty (length of words). 33 34 35 Returns: 36 * `int`: The number of letters (the difficulty) to use for the secret word 37 * or `"invalid"`: the string `"invalid" indicating that the person did not enter a valid number 38 """ 39 40 user_input = simpledialog.askstring( 41 title="Difficulty Level", prompt="What length word should we use?" 42 ) 43 44 ## TODO: Use try-except to try and see if user_input is a number 45 ## TODO: If they did, check to see if it"s at least 2 or at most 15. 46 ## TODO: If it is, then return that number 47 ## TODO: In all other cases, return the string "invalid" 48 49 50def read_in_words(file_path, num_letters): 51 """ 52 Function that reads in a list of words and adds them to the `GAME_DATA`. Then, 53 picks a random word to set as the "solution" key in the `GAME_DATA` dictionary. 54 55 Args: 56 * file_path (`str`): The file to be read in 57 * num_letters (`int`): How many letters should be in a word 58 59 Returns: 60 * a `list` continaing the words with the correct number of letters 61 """ 62 list_of_words = [] 63 64 ## TODO: Open the file stored in the file_path variable 65 66 ## TODO: loop through each line of the file 67 ## TODO: Split the line by " " using the split method of the String class 68 ## TODO: If the number of letters in that word matches num_letters 69 ## TODO Append the 0th element of that list into list_of_words 70 71 ## TODO: Close the file! 72 73 # You can print out the list of valid words if you need to for debugging 74 # print("A random word in our list:", choice(list_of_words)) 75 # print("Number of valid words:", len(list_of_words)) 76 77 return list_of_words 78 79 80def generate_hint(guess, solution): 81 """ 82 Generates a hint from a guess and a solution. 83 84 A hint string will be however many letters long the guess 85 and solution are, where each character represents the "correctness" 86 of the guess: 87 1. 🟩 for correct letters 88 2. 🟨 for partially correct letters 89 3. ⬜ for incorrect letters 90 91 Args: 92 * guess (`str`): The guess to be evaluated 93 * solution (`str`): The solution to be compared to 94 95 Returns: 96 * `hint` (`str`): The hint for the user 97 """ 98 99 # Loop through each letter of the entry and build a hint for each 100 # letter in our guess by comparing it to our solutions. Then return the hint. 101 hint = "" 102 103 ## TODO: Change this range to account for the fact that the solution / guess 104 ## could have more or less than 5 letters. 105 for i in range(0, 5, 1): 106 pass ## TODO: remove this pass once you"re working here 107 108 # TODO: If that letter matches the corresponding one in the solution 109 # then add a 🟩 to our hint (hint = hint + "🟩") 110 # Here"s an example of comparing specific letters 111 # guess[i] == solution[i] 112 113 # TODO: Else-if that letter is IN that word anywhere, 114 # then add a 🟨 to our hint (use the `in` operator!) 115 116 # TODO: Else, that letter isn"t in our word so add an ⬜ to our hint 117 118 return hint 119 120def finalize_guess(guess, hint): 121 """ 122 Finalizes a valid user guess. 123 124 This function does a few things: 125 1. It saves the current guess as a past guess 126 2. It clears out the current guess 127 3. It checks to see if the guess matches the solution 128 4. It checks to see if the user has reached the max number of guesses 129 130 Args: 131 * guess (`str`): The guess to be showed on the screen. 132 * hint (`str`): The evaluated hint so that we can color the blocks correctly. 133 134 Side-Effects: 135 * Appends a guess to GAME_DATA["past_guesses"] and checks to see if the game is over. 136 137 """ 138 # Append the inputted guess to the past_guesses list in GAME_DATA 139 GAME_DATA["past_guesses"].append(guess) 140 141 # Clear out the current guess 142 GAME_DATA["current_guess"] = "" 143 144 ## TODO: Change the one line below to account for the fact that a guess might have 145 ## greater or fewer than 5 letters 146 if hint == "🟩" * 5: 147 game_over(happy=True) 148 149 elif len(GAME_DATA["past_guesses"]) == 6: 150 game_over() 151 152 153def show_past_guess(past_guess, guess_number, hint): 154 """ 155 Shows a past guess on the screen. 156 157 Parameters: 158 * past_guess (`str`): The past guess to be showed (you can assume it"s valid and the correct length) 159 * guess_number (`int`): The number of the guess to be drawn (y-coordinate) 160 * hint (`str`): The hint string that was generated from that guess 161 162 Side-Effect: 163 * Draws to the screen 164 """ 165 ## TODO: Change the one line below to account for the fact that a guess might have 166 ## greater or fewer than 5 letters 167 for i in range(0, 5): 168 169 if hint[i] == "🟩": 170 color_a_grid_square(CORRECT_COLOR, (i, guess_number)) 171 172 elif hint[i] == "🟨": 173 color_a_grid_square(PARTIAL_COLOR, (i, guess_number)) 174 else: 175 color_a_grid_square(WRONG_COLOR, (i, guess_number)) 176 177 draw_letter_in_grid(past_guess[i], (i, guess_number), past_guess=True) 178 179def show_game_board(): 180 """ 181 Shows the game board. 182 183 Side-Effect: 184 * Draws to the screen 185 """ 186 # Clear the screen. 187 delete("all") 188 189 # Resize the window to accommodate for the correct number of characters 190 ## TODO: Change the one line below to account for the fact that a guess might have 191 ## greater or fewer than 5 letters 192 screen_width = 100 * 5 193 screen_height = 600 194 195 ## TODO: Change the one line below to account for the fact that a guess might have 196 ## greater or fewer than 5 letters 197 canvas.config(width=100 * 5, height=600) 198 199 # Draw the grid 200 make_grid(screen_width, screen_height) 201 202 # Load in the current guess from our GAME_DATA dictionary 203 current_guess = GAME_DATA["current_guess"] 204 205 # Load in the list of past guesses from our GAME_DATA dictionary 206 past_guesses = GAME_DATA["past_guesses"] 207 208 # Calculate how many guesses there have been by finding the length of the 209 # past_guesses list in our GAME_DATA dictionary 210 guess_count = len(GAME_DATA["past_guesses"]) 211 212 # Loop through all of the past guesses 213 for i in range(0, guess_count, 1): 214 show_past_guess(past_guesses[i], i, generate_hint(past_guesses[i], GAME_DATA["solution"])) 215 216 # Now loop through each letter of the current guess and draw it to the board 217 for i in range(0, len(current_guess), 1): 218 color_a_grid_square(DEFAULT_COLOR, (i, guess_count)) 219 draw_letter_in_grid(current_guess[i], (i, guess_count)) 220 221 # Update the game board 222 canvas.mainloop() 223 224########################## EVENT HANDLERS ############################## 225def handle_typing(event): 226 """ 227 Event handler for key presses in Wordle. 228 229 We need to handle 3 specific types of key presses: 230 1. `event.keysym == "BackSpace"` 231 2. `event.keysym == "Return"` 232 3. `len(event.keysym) == 1` (single character keys) 233 234 Args: 235 * `event`: The event to process. 236 237 Side-Effect: 238 * Draws to the screen and updates current_guess inside of GAME_DATA 239 """ 240 # If the player hits BackSpace, delete the last character from the 241 # "current_guess" key in the GAME_DATA dictionary 242 if event.keysym == "BackSpace": 243 GAME_DATA["current_guess"] = GAME_DATA["current_guess"][:-1] 244 245 # If the player hits Return... 246 elif event.keysym == "Return": 247 # First check that right num letters have been entered 248 ## TODO: Change the one line below to account for the fact that a guess might have 249 ## greater or fewer than 5 letters 250 if len(GAME_DATA["current_guess"]) != 5: 251 print("not enough letters") 252 # Next check if it"s a valid word in our word list 253 elif GAME_DATA["current_guess"] not in GAME_DATA["word_list"]: 254 print("not a valid word") 255 # If we make it past those two checks, it"s a valid guess 256 else: 257 # First generate a hint, then finalize the guess 258 hint = generate_hint(GAME_DATA["current_guess"], GAME_DATA["solution"]) 259 finalize_guess(GAME_DATA["current_guess"], hint) 260 261 # If the player hits any other letter/number/symbol on the keyboard 262 elif len(event.keysym) == 1: 263 # If the user hasn"t entered the right num letters, add the entered symbol 264 # to the current guess (make sure to convert it to upper case!) 265 ## TODO: Change the one line below to account for the fact that a valid guess might have 266 ## greater or fewer than 5 letters 267 if len(GAME_DATA["current_guess"]) < 5: 268 GAME_DATA["current_guess"] += event.keysym.upper() 269 270 # As long as the user hasn"t made 6 guesses, show the game board 271 if len(GAME_DATA["past_guesses"]) < 7: 272 show_game_board() 273 274 275########################## GAME SETUP AND PLAY ##!!##########################
def
get_difficulty():
31def get_difficulty(): 32 """ 33 Uses a pop-up window to ask the user to input the desired difficulty (length of words). 34 35 36 Returns: 37 * `int`: The number of letters (the difficulty) to use for the secret word 38 * or `"invalid"`: the string `"invalid" indicating that the person did not enter a valid number 39 """ 40 41 user_input = simpledialog.askstring( 42 title="Difficulty Level", prompt="What length word should we use?" 43 ) 44 45 ## TODO: Use try-except to try and see if user_input is a number 46 ## TODO: If they did, check to see if it"s at least 2 or at most 15. 47 ## TODO: If it is, then return that number 48 ## TODO: In all other cases, return the string "invalid"
Uses a pop-up window to ask the user to input the desired difficulty (length of words).
Returns:
int
: The number of letters (the difficulty) to use for the secret word- or
"invalid"
: the string `"invalid" indicating that the person did not enter a valid number
def
read_in_words(file_path, num_letters):
51def read_in_words(file_path, num_letters): 52 """ 53 Function that reads in a list of words and adds them to the `GAME_DATA`. Then, 54 picks a random word to set as the "solution" key in the `GAME_DATA` dictionary. 55 56 Args: 57 * file_path (`str`): The file to be read in 58 * num_letters (`int`): How many letters should be in a word 59 60 Returns: 61 * a `list` continaing the words with the correct number of letters 62 """ 63 list_of_words = [] 64 65 ## TODO: Open the file stored in the file_path variable 66 67 ## TODO: loop through each line of the file 68 ## TODO: Split the line by " " using the split method of the String class 69 ## TODO: If the number of letters in that word matches num_letters 70 ## TODO Append the 0th element of that list into list_of_words 71 72 ## TODO: Close the file! 73 74 # You can print out the list of valid words if you need to for debugging 75 # print("A random word in our list:", choice(list_of_words)) 76 # print("Number of valid words:", len(list_of_words)) 77 78 return list_of_words
Function that reads in a list of words and adds them to the GAME_DATA
. Then,
picks a random word to set as the "solution" key in the GAME_DATA
dictionary.
Args:
- file_path (
str
): The file to be read in - num_letters (
int
): How many letters should be in a word
Returns:
- a
list
continaing the words with the correct number of letters
def
generate_hint(guess, solution):
81def generate_hint(guess, solution): 82 """ 83 Generates a hint from a guess and a solution. 84 85 A hint string will be however many letters long the guess 86 and solution are, where each character represents the "correctness" 87 of the guess: 88 1. 🟩 for correct letters 89 2. 🟨 for partially correct letters 90 3. ⬜ for incorrect letters 91 92 Args: 93 * guess (`str`): The guess to be evaluated 94 * solution (`str`): The solution to be compared to 95 96 Returns: 97 * `hint` (`str`): The hint for the user 98 """ 99 100 # Loop through each letter of the entry and build a hint for each 101 # letter in our guess by comparing it to our solutions. Then return the hint. 102 hint = "" 103 104 ## TODO: Change this range to account for the fact that the solution / guess 105 ## could have more or less than 5 letters. 106 for i in range(0, 5, 1): 107 pass ## TODO: remove this pass once you"re working here 108 109 # TODO: If that letter matches the corresponding one in the solution 110 # then add a 🟩 to our hint (hint = hint + "🟩") 111 # Here"s an example of comparing specific letters 112 # guess[i] == solution[i] 113 114 # TODO: Else-if that letter is IN that word anywhere, 115 # then add a 🟨 to our hint (use the `in` operator!) 116 117 # TODO: Else, that letter isn"t in our word so add an ⬜ to our hint 118 119 return hint
Generates a hint from a guess and a solution.
A hint string will be however many letters long the guess and solution are, where each character represents the "correctness" of the guess:
- 🟩 for correct letters
- 🟨 for partially correct letters
- ⬜ for incorrect letters
Args:
- guess (
str
): The guess to be evaluated - solution (
str
): The solution to be compared to
Returns:
hint
(str
): The hint for the user
def
finalize_guess(guess, hint):
121def finalize_guess(guess, hint): 122 """ 123 Finalizes a valid user guess. 124 125 This function does a few things: 126 1. It saves the current guess as a past guess 127 2. It clears out the current guess 128 3. It checks to see if the guess matches the solution 129 4. It checks to see if the user has reached the max number of guesses 130 131 Args: 132 * guess (`str`): The guess to be showed on the screen. 133 * hint (`str`): The evaluated hint so that we can color the blocks correctly. 134 135 Side-Effects: 136 * Appends a guess to GAME_DATA["past_guesses"] and checks to see if the game is over. 137 138 """ 139 # Append the inputted guess to the past_guesses list in GAME_DATA 140 GAME_DATA["past_guesses"].append(guess) 141 142 # Clear out the current guess 143 GAME_DATA["current_guess"] = "" 144 145 ## TODO: Change the one line below to account for the fact that a guess might have 146 ## greater or fewer than 5 letters 147 if hint == "🟩" * 5: 148 game_over(happy=True) 149 150 elif len(GAME_DATA["past_guesses"]) == 6: 151 game_over()
Finalizes a valid user guess.
This function does a few things:
- It saves the current guess as a past guess
- It clears out the current guess
- It checks to see if the guess matches the solution
- It checks to see if the user has reached the max number of guesses
Args:
- guess (
str
): The guess to be showed on the screen. - hint (
str
): The evaluated hint so that we can color the blocks correctly.
Side-Effects:
- Appends a guess to GAME_DATA["past_guesses"] and checks to see if the game is over.
def
show_past_guess(past_guess, guess_number, hint):
154def show_past_guess(past_guess, guess_number, hint): 155 """ 156 Shows a past guess on the screen. 157 158 Parameters: 159 * past_guess (`str`): The past guess to be showed (you can assume it"s valid and the correct length) 160 * guess_number (`int`): The number of the guess to be drawn (y-coordinate) 161 * hint (`str`): The hint string that was generated from that guess 162 163 Side-Effect: 164 * Draws to the screen 165 """ 166 ## TODO: Change the one line below to account for the fact that a guess might have 167 ## greater or fewer than 5 letters 168 for i in range(0, 5): 169 170 if hint[i] == "🟩": 171 color_a_grid_square(CORRECT_COLOR, (i, guess_number)) 172 173 elif hint[i] == "🟨": 174 color_a_grid_square(PARTIAL_COLOR, (i, guess_number)) 175 else: 176 color_a_grid_square(WRONG_COLOR, (i, guess_number)) 177 178 draw_letter_in_grid(past_guess[i], (i, guess_number), past_guess=True)
Shows a past guess on the screen.
Parameters:
- past_guess (
str
): The past guess to be showed (you can assume it"s valid and the correct length) - guess_number (
int
): The number of the guess to be drawn (y-coordinate) - hint (
str
): The hint string that was generated from that guess
Side-Effect:
- Draws to the screen
def
show_game_board():
180def show_game_board(): 181 """ 182 Shows the game board. 183 184 Side-Effect: 185 * Draws to the screen 186 """ 187 # Clear the screen. 188 delete("all") 189 190 # Resize the window to accommodate for the correct number of characters 191 ## TODO: Change the one line below to account for the fact that a guess might have 192 ## greater or fewer than 5 letters 193 screen_width = 100 * 5 194 screen_height = 600 195 196 ## TODO: Change the one line below to account for the fact that a guess might have 197 ## greater or fewer than 5 letters 198 canvas.config(width=100 * 5, height=600) 199 200 # Draw the grid 201 make_grid(screen_width, screen_height) 202 203 # Load in the current guess from our GAME_DATA dictionary 204 current_guess = GAME_DATA["current_guess"] 205 206 # Load in the list of past guesses from our GAME_DATA dictionary 207 past_guesses = GAME_DATA["past_guesses"] 208 209 # Calculate how many guesses there have been by finding the length of the 210 # past_guesses list in our GAME_DATA dictionary 211 guess_count = len(GAME_DATA["past_guesses"]) 212 213 # Loop through all of the past guesses 214 for i in range(0, guess_count, 1): 215 show_past_guess(past_guesses[i], i, generate_hint(past_guesses[i], GAME_DATA["solution"])) 216 217 # Now loop through each letter of the current guess and draw it to the board 218 for i in range(0, len(current_guess), 1): 219 color_a_grid_square(DEFAULT_COLOR, (i, guess_count)) 220 draw_letter_in_grid(current_guess[i], (i, guess_count)) 221 222 # Update the game board 223 canvas.mainloop()
Shows the game board.
Side-Effect:
- Draws to the screen
def
handle_typing(event):
226def handle_typing(event): 227 """ 228 Event handler for key presses in Wordle. 229 230 We need to handle 3 specific types of key presses: 231 1. `event.keysym == "BackSpace"` 232 2. `event.keysym == "Return"` 233 3. `len(event.keysym) == 1` (single character keys) 234 235 Args: 236 * `event`: The event to process. 237 238 Side-Effect: 239 * Draws to the screen and updates current_guess inside of GAME_DATA 240 """ 241 # If the player hits BackSpace, delete the last character from the 242 # "current_guess" key in the GAME_DATA dictionary 243 if event.keysym == "BackSpace": 244 GAME_DATA["current_guess"] = GAME_DATA["current_guess"][:-1] 245 246 # If the player hits Return... 247 elif event.keysym == "Return": 248 # First check that right num letters have been entered 249 ## TODO: Change the one line below to account for the fact that a guess might have 250 ## greater or fewer than 5 letters 251 if len(GAME_DATA["current_guess"]) != 5: 252 print("not enough letters") 253 # Next check if it"s a valid word in our word list 254 elif GAME_DATA["current_guess"] not in GAME_DATA["word_list"]: 255 print("not a valid word") 256 # If we make it past those two checks, it"s a valid guess 257 else: 258 # First generate a hint, then finalize the guess 259 hint = generate_hint(GAME_DATA["current_guess"], GAME_DATA["solution"]) 260 finalize_guess(GAME_DATA["current_guess"], hint) 261 262 # If the player hits any other letter/number/symbol on the keyboard 263 elif len(event.keysym) == 1: 264 # If the user hasn"t entered the right num letters, add the entered symbol 265 # to the current guess (make sure to convert it to upper case!) 266 ## TODO: Change the one line below to account for the fact that a valid guess might have 267 ## greater or fewer than 5 letters 268 if len(GAME_DATA["current_guess"]) < 5: 269 GAME_DATA["current_guess"] += event.keysym.upper() 270 271 # As long as the user hasn"t made 6 guesses, show the game board 272 if len(GAME_DATA["past_guesses"]) < 7: 273 show_game_board()
Event handler for key presses in Wordle.
We need to handle 3 specific types of key presses:
event.keysym == "BackSpace"
event.keysym == "Return"
len(event.keysym) == 1
(single character keys)
Args:
event
: The event to process.
Side-Effect:
- Draws to the screen and updates current_guess inside of GAME_DATA