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

Simple Hangman game in Python

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

Problem

I recently started learning Python, and made a simple text based Hangman game. I wanted to know if there could be anything done to make the code cleaner or more efficient.

import random
import os
import sys

def main():
    pickword()

def start(word, twoplayer):
    wordarray = ''
    userguess = []
    guessright = 0
    lettersright = 0
    if len(word)  1 or guess1.isdigit():
        print("Invalid input")
        getuserguess(wordarray, userguess, tries, usedletters, word)
    else:
        checkuserguess(wordarray, userguess, guess1, usedletters, tries, word)

def lose(word):
    again = input("Sorry, you lost, the word was {}Would you like to play again[Y/N]".format(word))
    if again.lower() ==  "y":
        pickword()
    else:
        sys.exit()

def win():
    again = input("Congrats, you won hangman, do you want to play again?[Y/N]")
    if again == "Y" or "y":
        pickword()
    else:
        sys.exit()

def checkuserguess(wordarray, userguess, guess1, usedletters, tries, word):

    guess1list = (list(guess1))

    if guess1list[0] in usedletters:
        print("You already used that letter")
        getuserguess(wordarray, userguess, tries, usedletters, word)

    if guess1 in wordarray:
        usedletters.append(guess1)
        for i in range(0, len(wordarray)):
            if wordarray[i] == guess1list[0]:
                userguess[i] = guess1list[0]
                usedletters.append(guess1list[0])

        if "_ " not in userguess:
            print(' '.join(userguess))
            win()
        else:
            getuserguess(wordarray, userguess, tries, usedletters, word)

    else:
        if tries > 0:
            print("Sorry, that letter is not in the word, you have ", tries, " remaining")
            tries -= 1
            getuserguess(wordarray, userguess, tries, usedletters, word)
        else:
            lose(word)

main()

Solution

For this, I am going to go through your program in the order it is written:

-
Don't use if twoplayer == False:. You can simply say if not twoplayer: You don't even need that, though the first time because you do the same thing in the if and elseblocks.

-
You can use
" ".join("_" * lengthword) instead of for i in range(1, lengthword): userguess.append("_ "). Besides making it cleaner, you weren't adding enough underscores. The second argument to range() is exclusive. Imagine if the length of the word is two. In that case, range(1, 2) returns [1] because the second argument is exclusive. That has length 1 instead of the same length as the word: 2.

-
Don't use
wordarray.remove(wordarray[i]). Instead, use wordarray.pop(i). If you use .remove(), the first occurrence of the word will be removed, not necessarily the one you want to be removed.

-
When you ask
"Do you want to play 2 player?", you account for "y" and anything else. What if the user says "yes"? It would still count as no. Instead, you should use a while loop:

twoplayer = input("Do you want to play 2 player? [Y/N] ")
while twoplayer.lower() not in ("y", "n"):
    twoplayer = input("[Y/N] ")


-
Instead of setting
twoplayer inside of the if and else blocks, you can just do twoplayer = ("n", "y").index(twoplayer.lower())

-
If the word is too short, you don't want to call
pickword() again because pickword() asks "Do you want to play 2 player?" If the word is too short, that doesn't mean the user wants to change his mind on that question. Instead, use a loop:

while len(word) < 3:
    print("That word is too short")
    word = input("Player 1, enter the word you want player 2 to guess, don't let them see! ")


-
How do you know how many lines to print? Instead of printing an arbitrary number of lines,
print("\033c") will clear the terminal.

-
You call
start(word, twoplayer) in both the if and the else block. That is a sign that it shouldn't be in either one. Put it after both blocks so that you aren't duplicating code.

-
While we're at that point in the program, you want only one line in your
try: block: word = random.choice(...). twoplayer should be defined as I outlined above, so we don't need that here at all and start(word, twoplayer) will be outside of the if and else blocks, so we don't need that. Besides, the only reason you want the try block is because you are dealing with a file. If anything else is throwing an error, you want the traceback because it shouldn't be.

-
Don't use a bare
except: You have certain errors that you think you might get; list them here. In this case, it's except IOError:

-
sys.exit(), when given an argument, uses that argument as the exit code. In this case it is failure, so you should use sys.exit(1).

-
Your check for
guess1's validity is not the best. To make sure that it is one character, use len(guess1) != 1 as the check. Also, guess1.isdigit() is probably not the only thing that is invalid. For example, $ shouldn't be in the word, right? Instead, use not guess1.isalpha() to make sure it is an alphabetic character.

-
Instead of using recursion and typing out all of those variable names, use a loop:

print(' '.join(userguess))
guess = input("Enter your guess: ")
while len(guess) != 1 or not guess.isalpha():
    print("Invalid input")
    guess = input("Try again: ")

checkuserguess(wordarray, userguess, guess, usedletters, tries, word)


-
You have duplicate code in
lose() and win(): Would you like to play again. Instead, define a function that asks that question, and use it in lose() and win(). Make sure that in that function you use if again.lower() == "y": as you did in lose(). if again == "Y" or "y": does not work how you would expect it to. See this StackOverflow post for why.

-
You check if
"_ " is in userguess`, but you should be checking for just the underscore, not the underscore with a space. If the underscore is at the end of the word, there shouldn't be a space. If there is, you're doing it wrong and you shouldn't depend on it.

This is my first complete review, so if anyone has suggestions, I would be happy to modify it.

Code Snippets

twoplayer = input("Do you want to play 2 player? [Y/N] ")
while twoplayer.lower() not in ("y", "n"):
    twoplayer = input("[Y/N] ")
while len(word) < 3:
    print("That word is too short")
    word = input("Player 1, enter the word you want player 2 to guess, don't let them see! ")
print(' '.join(userguess))
guess = input("Enter your guess: ")
while len(guess) != 1 or not guess.isalpha():
    print("Invalid input")
    guess = input("Try again: ")

checkuserguess(wordarray, userguess, guess, usedletters, tries, word)

Context

StackExchange Code Review Q#122763, answer score: 8

Revisions (0)

No revisions yet.