HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMinor

First Hangman game

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
gamefirsthangman

Problem

This is my first ever program created after reading a book on Python. Do you have any suggestions for me? Anything that are considered bad habits that I should correct for my new project?

```
#HangMan - 2014
import random
import time

#TODO: add word support
#TODO: add already guessed letters

secret = ""
dash = ""
HANGMANPICS = ['''
+---+
| |
|
|
|
|
=========''', '''
+---+
| |
O |
|
|
|
=========''', '''
+---+
| |
O |
| |
|
|
=========''', '''
+---+
| |
O |
/| |
|
|
=========''', '''
+---+
| |
O |
/|\ |
|
|
=========''', '''
+---+
| |
O |
/|\ |
/ |
|
=========''', '''
+---+
| |
O |
/|\ |
/ \ |
|
=========''']

def create_hangman():
create_hangman.guessess = create_hangman.guessess = 0
create_hangman.already_guessed = ""
#List of words, pick a word, then set it to a var
words = ["soccer", "summer", "windows", "lights", "nighttime", "desktop", "walk"]
d = random.randint(0, 6)

#Tell the compiler we want the global secret var
global secret
#Change the global secret v to a string while we choose the word
secret = str(words[d])

#The blank spaces. Find how many letters the word is and replace it with underscores
create_hangman.dash = ['_' for x in range(len(secret))]

#Print the hangman
print(HANGMANPICS[0], "\n",' '.join(create_hangman.dash))

def add_letter(letter):
create_hangman.already_guessessed = create_hangman.already_guessed, letter

def guess():
while True:
think = input("Pick a letter: ")
letter = think
alreadyGuessed = ""
if(len(letter) != 1):
print("Please enter only one letter.")
elif(letter not in 'abcdefghijklmnopqrstuvwxyz'):
print("Please guess a letter.")
elif(letter not in secret):
wrong_word(create_hangman.guessess)
add_le

Solution

You are making a common beginner mistake of misusing functions as if they were goto labels. For example, from the last line of the program, you call guess(), which calls check(), which calls guess(), which calls check(), which calls guess(), …, which calls check(), which calls you_win(), which can call you_loose() (?!)

At some point, you can hit ControlC to see the deep call stack that results from this weird mutual recursion. A properly structured program should have a nice, simple stack trace.

See other examples of code with this problem:

  • Hangman



  • Number-guessing game



  • Rock-paper-scissors



  • Mileage calculator



Here is an implementation restructured to use functions properly. Note the use of while loops.

The state of a game, at any point in a game, is entirely summarized by secret and guesses. Therefore, those two variables are frequently passed from calls within play_hangman(). An object-oriented solution would avoid such parameter passing, but I opted to stay somewhat close to the original design instead.

import random

HANGMANPICS = …

def pick_word():
    """Return a random word from the word bank."""
    words = ["soccer", "summer", "windows", "lights", "nighttime", "desktop", "walk"]
    return random.choice(words)

def print_hangman(secret, guesses):
    """Print the gallows, the man, and the blanked-out secret."""
    wrong_guesses = [guess for guess in guesses if not guess in secret]
    word_display = ' '.join(letter if letter in guesses else '_' for letter in secret)
    print(HANGMANPICS[len(wrong_guesses)])
    print()
    print(word_display)

def guess(secret, guesses):
    """Prompt for a single letter, append it to guesses, and return the guess."""
    while True:
        letter = input("Pick a letter: ")
        if len(letter) != 1:
            print("Please enter only one letter.")
        elif letter not in 'abcdefghijklmnopqrstuvwxyz':
            print("Please guess a letter.")
        else:
            guesses.append(letter)
            return letter

def won(secret, guesses):
    """Check whether the secret has been guessed."""
    right_guesses = [letter for letter in secret if letter in guesses]
    return len(right_guesses) >= len(secret)

def hanged(secret, guesses):
    """Check whether too many guesses have been made."""
    wrong_guesses = [guess for guess in guesses if not guess in secret]
    return len(wrong_guesses) >= len(HANGMANPICS)

def play_hangman():
    """Play one game of hangman. Return True if the player won."""
    secret = pick_word()
    guesses = []
    message = None
    while not hanged(secret, guesses):
        print_hangman(secret, guesses)
        if message is not None:
            print()
            print(message)
        new_guess = guess(secret, guesses)
        if won(secret, guesses):
            print("Congratulations! You won and got the word", secret)
            return True
        elif new_guess in secret:
            message = "Congratulations! {0} was found!".format(new_guess)
        else:
            message = "That letter is not in the word."
    print("Sorry you lost! The correct word was", secret)
    return False

def play_again():
    while True:
        play_again = input("Would you like to play again: ");
        if play_again == "Y" or play_again == "y":
            print("Creating a new game...")
            return True
        elif play_again == "N" or play_again == "n":
            print("Thanks for playing, bye!")
            return False
        else:
            print("Error: Please choose either 'Y' or 'N'")

while True:
    play_hangman()
    if not play_again():
        break

Code Snippets

import random

HANGMANPICS = …

def pick_word():
    """Return a random word from the word bank."""
    words = ["soccer", "summer", "windows", "lights", "nighttime", "desktop", "walk"]
    return random.choice(words)

def print_hangman(secret, guesses):
    """Print the gallows, the man, and the blanked-out secret."""
    wrong_guesses = [guess for guess in guesses if not guess in secret]
    word_display = ' '.join(letter if letter in guesses else '_' for letter in secret)
    print(HANGMANPICS[len(wrong_guesses)])
    print()
    print(word_display)

def guess(secret, guesses):
    """Prompt for a single letter, append it to guesses, and return the guess."""
    while True:
        letter = input("Pick a letter: ")
        if len(letter) != 1:
            print("Please enter only one letter.")
        elif letter not in 'abcdefghijklmnopqrstuvwxyz':
            print("Please guess a letter.")
        else:
            guesses.append(letter)
            return letter

def won(secret, guesses):
    """Check whether the secret has been guessed."""
    right_guesses = [letter for letter in secret if letter in guesses]
    return len(right_guesses) >= len(secret)

def hanged(secret, guesses):
    """Check whether too many guesses have been made."""
    wrong_guesses = [guess for guess in guesses if not guess in secret]
    return len(wrong_guesses) >= len(HANGMANPICS)

def play_hangman():
    """Play one game of hangman. Return True if the player won."""
    secret = pick_word()
    guesses = []
    message = None
    while not hanged(secret, guesses):
        print_hangman(secret, guesses)
        if message is not None:
            print()
            print(message)
        new_guess = guess(secret, guesses)
        if won(secret, guesses):
            print("Congratulations! You won and got the word", secret)
            return True
        elif new_guess in secret:
            message = "Congratulations! {0} was found!".format(new_guess)
        else:
            message = "That letter is not in the word."
    print("Sorry you lost! The correct word was", secret)
    return False

def play_again():
    while True:
        play_again = input("Would you like to play again: ");
        if play_again == "Y" or play_again == "y":
            print("Creating a new game...")
            return True
        elif play_again == "N" or play_again == "n":
            print("Thanks for playing, bye!")
            return False
        else:
            print("Error: Please choose either 'Y' or 'N'")

while True:
    play_hangman()
    if not play_again():
        break

Context

StackExchange Code Review Q#72193, answer score: 8

Revisions (0)

No revisions yet.