Possum - Olga O.#23
Conversation
anselrognlie
left a comment
There was a problem hiding this comment.
Looks good! Please review my comments, and let me know if you have any questions. Nice job!
| wrong_guesses_list =[] | ||
| correct_letter_guess_statuses = build_letter_status_dict(snowman_word) |
There was a problem hiding this comment.
👍 These are the two pieces of data we need to make use of our other helper functions for tracking correct and incorrect guesses. Tracking the letter status involves using a dictionary with a particular structure, which our build_letter_status_dict helper is able to calculate from the random word.
The extra variable for tracking the count of wrong guesses isn't really needed, since we can always look up the number of wrong guesses as needed by getting the len() of the wrong_guesses_list, though having a named variable can help make it clear why we're getting that value.
| correct_letter_guess_statuses = build_letter_status_dict(snowman_word) | ||
| wrong_guesses_count = 0 | ||
|
|
||
| while wrong_guesses_count < SNOWMAN_MAX_WRONG_GUESSES and not is_word_guessed(snowman_word, correct_letter_guess_statuses): |
There was a problem hiding this comment.
The main guide describing how to format our Python code (PEP8) suggests a maximum line length of 79 characters. It can be OK to go a little over, but if it gets too much longer, we should wrap our lines. PEP8 suggests doing this by surrounding our long expressions in parentheses, which lets us wrap lines anywhere we like.
while (wrong_guesses_count < SNOWMAN_MAX_WRONG_GUESSES
and not is_word_guessed(snowman_word, correct_letter_guess_statuses)):There was a problem hiding this comment.
Alternatively, we could shorten this condition to focus solely on the number of guesses, and have a check within the loop for whether the word has been guessed.
while wrong_guesses_count < SNOWMAN_MAX_WRONG_GUESSES:
# later
if is_word_guessed(snowman_word, correct_letter_guess_statuses):
print("Congratulations, you win!")
print_word_progress_string(snowman_word, correct_letter_guess_statuses)
returnThere was a problem hiding this comment.
We can use a similar approach in our homework exercise on loops. Within the body of the function silly_num(), we can either:
- run a lop with two conditions after the key word 'while': while num != 0 and my_sum < 1000 or
- check within the loop for whether the num equals to 0 and if it does - break the loop
def silly_sum():
total = 0
num = 1
while num != 0 and my_sum < 1000:
num = input_int()
total += num
return `total
def silly_sum():
total = 0
while total < 1000:
num = input_int()
if num == 0:
break
total += num
return total
| wrong_guesses_count = 0 | ||
|
|
||
| while wrong_guesses_count < SNOWMAN_MAX_WRONG_GUESSES and not is_word_guessed(snowman_word, correct_letter_guess_statuses): | ||
| print_word_progress_string(snowman_word, correct_letter_guess_statuses) |
There was a problem hiding this comment.
👍 Displaying the word status before the guess means that the player gets to see the length of the word before guessing. This wasn't a requirement, but it's nice to have from a gameplay perspective.
| while wrong_guesses_count < SNOWMAN_MAX_WRONG_GUESSES and not is_word_guessed(snowman_word, correct_letter_guess_statuses): | ||
| print_word_progress_string(snowman_word, correct_letter_guess_statuses) | ||
| user_input = get_letter_from_user(correct_letter_guess_statuses, wrong_guesses_list) | ||
| if user_input in snowman_word: |
There was a problem hiding this comment.
Checking that the guessed letter is in the word is a valid way to check whether this was a correct letter. We haven't discussed this yet, but checking whether a letter is in a string requires Python to check each letter one by one, while checking whether a letter is the key of the correct_letter_guess_statuses dict (also performed with the in operator) can theoretically be performed with a single computation. It won't matter much in this small program, but it's helpful to start thinking about these differences and biasing our choices towards efficiency!
| print("You guessed the letter!") | ||
| else: | ||
| wrong_guesses_list.append(user_input) | ||
| wrong_guesses_count = len(wrong_guesses_list) |
There was a problem hiding this comment.
If you are going to use a helper variable to track the wrong guesses, then I like that you are updating it by reading the list len() rather than incrementing a count. This helps ensure that the data stays in sync. In a project of this size, it's pretty easy to ensure that all the places the list length changes also update the wrong guess count, but in larger projects, it can be more challenging to ensure multiple related variables are always updated together, whcih is why we might elect to do without the extra named variable.
| wrong_guesses_list.append(user_input) | ||
| wrong_guesses_count = len(wrong_guesses_list) | ||
| print("This letter is not in the snowman word.") | ||
| print_snowman_graphic(wrong_guesses_count) |
There was a problem hiding this comment.
Consider printing status information, including the word progress (shows correct letters), the incorrect letters, and the snowman graphic, each time through the loop regardless of whether the previous letter was correct or incorrect. Having a consistent set of information can make it easier for the player to understand their situation and can help avoid the issue of information potentially scrolling off the screen.
Here, we only show the snowman graphic (which tells us how many wrong guesses remain) after a wrong guess. but this could scroll off the screen leaving us not knowing how many remain. It would also be helpful to show the user which wrong letters they've already guessed to help them think of possible words. The input routine will properly reject a duplicate guess, but having more information available to the player can help them guess.
There was a problem hiding this comment.
"having a consistent set of information" - noted. Thanks!
| wrong_guesses_count = len(wrong_guesses_list) | ||
| print("This letter is not in the snowman word.") | ||
| print_snowman_graphic(wrong_guesses_count) | ||
| if is_word_guessed(snowman_word, correct_letter_guess_statuses): |
There was a problem hiding this comment.
Because of the word guessed check here, we could remove the not word guessed check from the loop control condition, since this break logic would cause the loop to terminate before the condition would. Further, since you're using while/else logic, we only want the loop to exit normally for losing the game, since the else logic is handling the game loss situation.
| else: | ||
| print(f"'Sorry, you lose! The word was {snowman_word}'") |
There was a problem hiding this comment.
Loops with else are very specific to Python. As a result, they don't get used that often, and it usually takes programmers more effort to understand logic that depends on them. You're free to use them, but it can be helpful to think about how we could express this same logic (exiting the loop with victory skips this logic, while exiting by losing runs this logic) without the use of while/else.
For instance, if the win logic returned rather than performed a break, the function would exit on victory without reaching any code that follows the loop. So if we moved this code to the area after the loop (without the else) then we would know that logic only runs when the game is lost.
Many style guides recommend avoiding while/else or for/else other than simple cases of searching through data. Here, it's being used for general logic, which makes it a little more difficult to understand.
There was a problem hiding this comment.
"Many style guides recommend avoiding while/else or for/else" - thank you very much for this, Ansel. Good to know.
No description provided.