14
\$\begingroup\$

I started learning Python a couple of weeks ago and decided to make a game of Hangman. Some of the features:

  • Take in player name
  • Allow them to pick and change difficulty level
  • Play again when the game is over

I would love suggestions on how to make the code more pythonic and better overall.

import random
import sys

#Gallow printouts
gallows = ["_______\n|     |\n|     O\n|    -|-\n|     |\n|    / \\ \n|\n=======",
       "_______\n|     |\n|     O\n|    -|-\n|     |\n|    /\n|\n=======",
       "_______\n|     |\n|     O\n|    -|-\n|     |\n|\n|\n=======",
       "_______\n|     |\n|     O\n|    -|\n|     |\n|\n|\n=======",
       "_______\n|     |\n|     O\n|     |\n|     |\n|\n|\n=======",
       "_______\n|     |\n|     O\n|\n|\n|\n|\n=======",
       "_______\n|     |\n|\n|\n|\n|\n|\n=======",
      ]

# Lists containing the words for the game
five_letters = ['ankle', 'apple', 'birds', 'aunts', 'blood',
         'bones', 'forty', 'glitz', 'gnome', 'goats',
          'fairy', 'gator', 'glass', 'kneel', 'laces',
          'patio', 'party', 'taffy', 'zones', 'wages'
         ]
ten_letters = ['jackrabbit', 'maximizers', 'abnormally', 'abolishers', 'adrenaline',
        'california', 'basketball', 'friendship', 'renovation', 'skateboard',
        'understand', 'leadership', 'restaurant', 'generation', 'girlfriend',
        'vegetables', 'protection', 'trampoline', 'rainforest', 'instrument']
fifteen_letters = ['maneuverability', 'insubordination', 'excommunication', 'acclimatization',
             'rationalisation', 'mischievousness', 'kindheartedness', 'procrastinating',
            'confidentiality', 'instrumentation', 'inaccessibility', 'marginalization']

#Program Functions
def pick_diff():
    """Let the player pick and confirm a difficulty level."""
    prompt = "Pick a difficulty, please. (Easy, Medium, Hard)\n>"
    choice = ""
    while choice not in ['easy', 'medium', 'hard']:
        choice = input(prompt)
        choice = choice.lower()
    change_diff(choice)

def change_diff(level):
    """Allow the player a chance to change difficulty."""
    message = "\nYou picked " + level + ". Do you want to change it? [Y/N]\n>"
    answer = ""
    while answer not in ['y', 'n']:
        answer = input(message)
        answer = answer.lower()
    if answer == 'y':
        pick_diff()
    if answer == 'n':
        print("\nLET'S PLAY!\n")
        choose_word(level)

def choose_word(choice):
    """Assign the game word based on player difficulty choice."""
    if choice == 'easy':
        word = random.choice(five_letters)
    elif choice == 'medium':
        word = random.choice(ten_letters)
    elif choice == 'hard':
        word = random.choice(fifteen_letters)
    play_game(word)

def play_game(this_word):
    """Run the actual game of hangman."""
    word = list(this_word)
    blanks = "_" * len(word)
    blanks = list(blanks)
    guessed = []
    incorrect = 6
    while incorrect > 0:
        print("\n" + gallows[incorrect]
              + "\nYou have {} chances left.".format(incorrect)
              + "\nYour word: " + "".join(blanks)
              + "\nGuessed letters: " + ", ".join(guessed)
             )
        letter = input("Your guess: ").lower()
        if len(letter) == 1 and letter.isalpha():
            if letter in guessed:
                print("\n\nYou already guessed that!")
            elif letter in word:
                for index,character in enumerate(word):
                    blanks = list(blanks)
                    if character == letter:
                        blanks[index] = letter
                        current = "".join(blanks)
                        if blanks == word:
                            print("\n\nCONGRATULATIONS, YOU WON!!\nYour word was " + ''.join(word) + ".\n")
                            play_again()
            elif letter not in word:
                incorrect -= 1
                guessed.append(letter)
        else:
            print("\n\n!Only single letters allowed!\n\n")
    else:
        print(gallows[0])
        print("\nSorry " + player + ", your game is over!\nYour word was " + ''.join(word) + ".")
        play_again()

def play_again():
    """Offer the player a chance to play again."""
    repeat = input("Would you like to play again " + player + "? [Y/N]\n>").lower()
    if repeat == 'y':
        print("Let's play!")
        pick_difficulty()
    else:
        print("Thanks for playing! Have a great day!")
        sys.exit()

# Welcome the player, get their name and explain the game.
player = input("Let's play hangman! Please type your name.\n>").lower()
player = player.title()
print("\nHey, " + player + "!\nYou get six incorrect guesses before you lose.\nWhich difficulty would you like?\n  Easy - Five letter word\n  Medium - Ten letter word\n  Hard - Fifteen letter word")

# Select the difficulty and begin the game
difficulty = pick_diff()
\$\endgroup\$
  • 1
    \$\begingroup\$ python 2 or python 3? looks like python 3, please correct either the title or the tag \$\endgroup\$ – Aemyl May 22 '17 at 5:35
  • \$\begingroup\$ This code doesn't work — I think there's been some kind of copy–paste error. @Robert, can you fix it? \$\endgroup\$ – Gareth Rees May 22 '17 at 19:41
  • \$\begingroup\$ @Gareth Rees I'll have a look tonight. It was having a fit when I tried to paste it but I thought I correct it. It's also on GitHub here github.com/robwa10/Hangman \$\endgroup\$ – Robert Hubbard May 22 '17 at 19:49
7
\$\begingroup\$

Good work! I applaud you on maintaining readability and having a compartmentalized, functional program. From a glance I suggest this:

Lines 32 and similar input()'s: make them like choice = input(prompt). As your code is now you must enter the while loop at least once.

Lines 34 and similar: you can do things like choice = input("bla bla").lower(), which you do later in the code anyways.

Lines 64 & 65: combine to blanks = list("_" * len(word))

Line 80: blanks = list(blanks) is not needed.

Line 83: currents is never used.

Lines 108 & 109: You can do player = input("bla bla").title()"

\$\endgroup\$
  • \$\begingroup\$ Thanks for the helpful comments! I´ve been doing some work with openpyxl these last few days and have realized the brevity of adding .lower(), etc. to the end of lines. And a definite thanks for pointing out where I forgot to delete line 83 after I changed the code above it. \$\endgroup\$ – Robert Hubbard May 24 '17 at 2:33
2
\$\begingroup\$

I think

player = input("bla bla").lower()
player = player.title()

can be combined to

player = input("bla bla").title()

title() except form casing first letter of each word lowers the later ones

\$\endgroup\$
2
\$\begingroup\$

The code is good, big up, but the user doesn't know exactly how many words he or she is supposed to play with.

\$\endgroup\$
2
\$\begingroup\$

Very good work I learned some new things checking out your code. I did notice one thing when running it on my end. I was not able to run the game again when it asks "would you like to play again"

line 116: pick_difficulty() should have been pick_diff()

other than that it works great.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.