Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 26 additions & 7 deletions game.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,32 @@


def snowman(snowman_word):
"""Complete the snowman function
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Docstrings are often a great way to explain what the following function does and how it operates. It is very common practice to see docstrings at the start of every function. If that is the case, no need to remove them! Go ahead and keep them in, especially if they exist in both finished and unfinished functions. This is a good indicator that the programmer intended for them to stay! In this case, rather than get rid of the docstring, it may be a good idea to update it to reflect the inputs, outputs and way this function works! You can use the other docstrings for guidance!

replace "pass" below with your own code
It should print 'Congratulations, you win!'
If the player wins and,
'Sorry, you lose! The word was {snowman_word}' if the player loses
"""
pass
correct_letter_guess_statuses = build_letter_status_dict(snowman_word)
wrong_guesses_list = []
player_won = False
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In many cases, holding a boolean value in a variable can be a great way to control a loop. One big exception is when that variable holds a boolean value that can easily be found in a more established way. For example, this variable tells us whether or not the player has currently won. The only place where it is used is in the conditional on line 41. We currently have a method (is_word_guessed) and a conditional statement (len(wrong_guesses_list) < SNOWMAN_WRONG_GUESSES) that could also be used to determine whether or not the player has won. As a result, the player_won variable technically ends up holding duplicate information where one of the other two approaches would suffice.

Another aspect of this involves comments I make later in this feedback that show that the final conditional can be avoided entirely with minimal changes to the rest of the program. If we approached it that way, we wouldn't need this variable at all!


while len(wrong_guesses_list) < SNOWMAN_MAX_WRONG_GUESSES:
user_input = get_letter_from_user(correct_letter_guess_statuses, wrong_guesses_list)
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When it comes to writing Python code, one of the guides you'll see us reference is the PEP 8 Style Guide. This is a guide for best practices when it comes to styling our code. One of the most common things we see is to try and keep individual lines of code under 79 characters. This line currently goes past that limit! It won't cause the code to break or anything, but it is a good thing to keep in mind in terms of readability and best practices!

I currently see two possible fixes here:

  1. Shorter and more concise variable names:

    • While there is no hard and fast rule on how long variable names should be, we could first try shortening the variable names we use here (correct_letter_guess_statuses and wrong_guesses_list) as they are on the longer side. That being said, these names match the parameters for the function you use to call them, which is good practice, so we'll need a different approach (but shorter variable names can help with this in other circumstances).
  2. Restyle the Function Call:

    • This is a great trick to have up your sleeve when making a function call that either includes multiple parameters or starts to approach that 79 character line limit! We can drop the parameters to the next line(s) to look something like the following:
    Suggested change
    user_input = get_letter_from_user(correct_letter_guess_statuses, wrong_guesses_list)
    user_input = get_letter_from_user(
    correct_letter_guess_statuses,
    wrong_guesses_list
    )
    • This is known as Implicit Line Continuation in Python. Whenever we have information nested inside parentheses, brackets or curly braces, we can drop the nested information to new lines without any specific notation!


if user_input in correct_letter_guess_statuses:
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just wanted to highlight a really cool thing that you did here! When we receive a letter from the user, we want to check to see if the letter exists within the word or not. Given the way this program is set up, we actually end up with two different collections that hold all the letters of the word, a string (snowman_word) and a dictionary (correct_letter_guess_statuses).

While we could check either one for the letter we've received, searching within a dictionary is ever so slightly more efficient than searching through a string (We'll talk more about why in Unit 1), so great choice here!

print("You guessed a letter that's in the word!")
correct_letter_guess_statuses[user_input] = True
else:
print(f"The letter {user_input} is not in the word")
wrong_guesses_list.append(user_input)

if is_word_guessed(snowman_word, correct_letter_guess_statuses):
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With this particular program, we have two potential finish conditions: 1. We find the word, 2. We use up all our guesses. One is a win condition and one is a lose condition.

There are a couple different ways we could handle these two conditions:

  1. Place both in a compound conditional within the while loop.
  2. Use one as the while loop conditional and nest the other conditional within the while loop.

You have opted for the latter, which I think makes sense for a few reasons:

  1. If we check both for each iteration, our loop ends if either the win or lose condition is met. This means that we are going to have to make an additional and unnecessary check after the loop to see which condition was met.
  2. If we meet one of the conditions inside the loop, we can exit the function early! This is important because you've specifically chosen to guide your loop with the condition that has a higher threshold to meet.

The one small change I would make is to use a return as opposed to a break. Explicit returns will stop the function as soon as they are reached whereas a break statement just pops us out of the current loop. Because you have only broken out of the loop, you are forced to include the extra conditional on line 41. If we simply stopped the function as soon as the word is guessed, we could avoid making this extra check (more on that in a second). The only trade off is that we would want to include an explicit return at the end of the function as well to maintain consistency.

print_word_progress_string(snowman_word, correct_letter_guess_statuses)
print("Congratulations, you win!")
player_won = True
break

print_snowman_graphic(len(wrong_guesses_list))
print_word_progress_string(snowman_word, correct_letter_guess_statuses)
print(f"Wrong guesses: {wrong_guesses_list}")

if not player_won:
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As a bit of a continuation to the previous piece of feedback, if we have a while loop that is governed by a specific conditional, it's a good idea to try avoiding extra conditionals after the while loop, especially if they make a similar check to the check made in the while loop!

print(f"Sorry, you lose! The word was {snowman_word}.")


def print_snowman_graphic(wrong_guesses_count):
Expand Down