patternpythonMinor
Hangman implementation for teaching a Python course
Viewed 0 times
coursehangmanteachingpythonforimplementation
Problem
I am teaching a Python crash course and thought a Hangman rendition would be fruitful.
I have an end product that I'll work towards with the hour that I have for the course and I was wondering what could be refactored or implemented to help the exchange of information from myself, intermediate level, to absolute beginners.
```
from random import choice
import os
def clear():
os.system('clear')
def play_again():
play_again = input("\nPlay again? Y/n ").lower()
if play_again != 'n':
clear()
game()
else:
print("\n\n\n\nCatch ya later!\n\n\n\n")
def get_secret_word():
words = ['angry', 'beautiful', 'brave', 'careful', 'charismatic', 'clever',
'creative', 'cute', 'dangerous', 'exciting', 'famous', 'friendly',
'happy', 'interesting', 'lucky', 'profound', 'popular', 'rich',
'thin', 'young']
secret_word = choice(words)
return secret_word
def get_guess(bad_guesses, good_guesses, secret_word):
while True:
guess = input("Guess a letter: ").lower()
if guess == '':
print("What was that?")
board(bad_guesses, good_guesses, secret_word)
elif len(guess) != 1:
input("You can only guess a single letter!")
board(bad_guesses, good_guesses, secret_word)
elif guess in bad_guesses or guess in good_guesses:
input("You've already guessed that letter!")
board(bad_guesses, good_guesses, secret_word)
elif not guess.isalpha():
input("You can only guess LETTERS!")
board(bad_guesses, good_guesses, secret_word)
else:
return guess
def board(bad_guesses, good_guesses, secret_word):
clear()
print(' Strikes: {}/8 '.format(len(bad_guesses)))
print('')
for guess in bad_guesses:
print(guess, end=" ")
print('\n\n')
for guess in secret_word:
if guess in good_guesses:
print(guess, end=" ")
I have an end product that I'll work towards with the hour that I have for the course and I was wondering what could be refactored or implemented to help the exchange of information from myself, intermediate level, to absolute beginners.
```
from random import choice
import os
def clear():
os.system('clear')
def play_again():
play_again = input("\nPlay again? Y/n ").lower()
if play_again != 'n':
clear()
game()
else:
print("\n\n\n\nCatch ya later!\n\n\n\n")
def get_secret_word():
words = ['angry', 'beautiful', 'brave', 'careful', 'charismatic', 'clever',
'creative', 'cute', 'dangerous', 'exciting', 'famous', 'friendly',
'happy', 'interesting', 'lucky', 'profound', 'popular', 'rich',
'thin', 'young']
secret_word = choice(words)
return secret_word
def get_guess(bad_guesses, good_guesses, secret_word):
while True:
guess = input("Guess a letter: ").lower()
if guess == '':
print("What was that?")
board(bad_guesses, good_guesses, secret_word)
elif len(guess) != 1:
input("You can only guess a single letter!")
board(bad_guesses, good_guesses, secret_word)
elif guess in bad_guesses or guess in good_guesses:
input("You've already guessed that letter!")
board(bad_guesses, good_guesses, secret_word)
elif not guess.isalpha():
input("You can only guess LETTERS!")
board(bad_guesses, good_guesses, secret_word)
else:
return guess
def board(bad_guesses, good_guesses, secret_word):
clear()
print(' Strikes: {}/8 '.format(len(bad_guesses)))
print('')
for guess in bad_guesses:
print(guess, end=" ")
print('\n\n')
for guess in secret_word:
if guess in good_guesses:
print(guess, end=" ")
Solution
I could come up with a laundry list of improvements. However, I would like to focus on just one issue, which makes your code an unforgivably bad example for your students: you are misusing functions as goto labels.
Note that
If you want to do something repeatedly in Python, use a loop. A reasonable outline would look like this:
Additional remarks:
Oh, and one more thing, since you should be setting a good example for your students: write a docstring for every function.
Note that
game() can call play_again(), which in turn may call game(). This mutual recursion is inappropriate. If you play many games, then hit CtrlC, you will see that the deepening stack is keeping track of all the previous calls, uselessly preparing for resuming execution after a return.If you want to do something repeatedly in Python, use a loop. A reasonable outline would look like this:
def play_again():
"""
Ask the player whether to play again.
"""
return 'n' != input("\nPlay again? Y/n ").lower()
def game():
"""
Play a single game of Hangman. Return True if the player wins,
or False if the player loses.
"""
secret_word = get_secret_word()
good_guesses = []
bad_guesses = []
while True:
board(bad_guesses, good_guesses, secret_word)
guess = get_guess(bad_guesses, good_guesses, secret_word)
if guess in secret_word:
good_guesses.append(guess)
if all(letter in good_guesses for letter in secret_word):
print("\nYou win!\n")
print("The secret word was {}.".format(secret_word.upper()))
return True
else:
bad_guesses.append(guess)
if len(bad_guesses) == 8:
clear()
print("\n ** ENGHH! ** ")
print("\nStrike ! You lost!")
print("\nThe secret word was {}".format(secret_word.upper()))
return False
def main():
"""
Play games of Hangman until the user decides to quit.
"""
while True:
game()
if not play_again():
print("\n\n\n\nCatch ya later!\n\n\n\n")
break
clear()Additional remarks:
- Flag variables, like
game_doneandfound, are almost always a bad idea. Here,game_donecan be eliminated by using proper looping technique, andfoundcan be determined using theall()function.
if guess not in secret_wordis redundant. You can just sayelse.
Oh, and one more thing, since you should be setting a good example for your students: write a docstring for every function.
Code Snippets
def play_again():
"""
Ask the player whether to play again.
"""
return 'n' != input("\nPlay again? Y/n ").lower()
def game():
"""
Play a single game of Hangman. Return True if the player wins,
or False if the player loses.
"""
secret_word = get_secret_word()
good_guesses = []
bad_guesses = []
while True:
board(bad_guesses, good_guesses, secret_word)
guess = get_guess(bad_guesses, good_guesses, secret_word)
if guess in secret_word:
good_guesses.append(guess)
if all(letter in good_guesses for letter in secret_word):
print("\nYou win!\n")
print("The secret word was {}.".format(secret_word.upper()))
return True
else:
bad_guesses.append(guess)
if len(bad_guesses) == 8:
clear()
print("\n ** ENGHH! ** ")
print("\nStrike ! You lost!")
print("\nThe secret word was {}".format(secret_word.upper()))
return False
def main():
"""
Play games of Hangman until the user decides to quit.
"""
while True:
game()
if not play_again():
print("\n\n\n\nCatch ya later!\n\n\n\n")
break
clear()Context
StackExchange Code Review Q#162198, answer score: 8
Revisions (0)
No revisions yet.