6
\$\begingroup\$

I have just made a game called Hangman. I have added some stuff which people don't normally use, like cheat-code/s, time.sleep().

How can I improve this, in both readability and methodology?

import random
import time


hangman = (

"""
   _________
    |/        
    |              
    |                
    |                 
    |               
    |                   
    |___                 
    """,

"""
   _________
    |/   |      
    |              
    |                
    |                 
    |               
    |                   
    |___                 
    H""",

"""
   _________       
    |/   |              
    |   (_)
    |                         
    |                       
    |                         
    |                          
    |___                       
    HA""",

"""
   ________               
    |/   |                   
    |   (_)                  
    |    |                     
    |    |                    
    |                           
    |                            
    |___                    
    HAN""",


"""
   _________             
    |/   |               
    |   (_)                   
    |   /|                     
    |    |                    
    |                        
    |                          
    |___                          
    HANG""",


"""
   _________              
    |/   |                     
    |   (_)                     
    |   /|\                    
    |    |                       
    |                             
    |                            
    |___                          
    HANGM""",



"""
   ________                   
    |/   |                         
    |   (_)                      
    |   /|\                             
    |    |                          
    |   /                            
    |                                  
    |___                              
    HANGMA""",


"""
   ________
    |/   |     
    |   (_)    
    |   /|\           
    |    |        
    |   / \        
    |               
    |___           
    HANGMAN""")

wrong = 0
used = []
password = "python".upper()

words = open("word.txt", "r").read().split()

words = str(random.choice(words).upper())


print " "
print "-----Welcome to HANGMAN, You get seven chances to guess the mystery word-----"
print " "

max_wrong = len(hangman) - 1



so_far = "*" * len(words)   
print "You need to guess", len(words), "letters word"
while wrong < max_wrong and so_far != words:


    print hangman[wrong]

    print "\nYou've used the following letters:\n", used
    print "\nSo far, the word is:\n", so_far

    inp = raw_input("Pick a letter----->").upper()

    if inp == password:
        print " "
        print "please wait..."
        time.sleep(3)
        print "cheat-code activated"
        print " "
        print "Correct word is", words
        exit()

    if inp.isdigit() is True=:
        print "Invalid Input"
        continue

    if len(inp) > 1:
        print "Invalid Input"
        continue
    while inp in used:
        print "You've already guessed the letter:", inp
        inp = raw_input("Pick a letter----->").upper()


        if inp.isalpha() is False:
            print "Invalid Input"
            continue

        if len(inp) > 1:
            print "Invalid Input"
            continue

    used.append(inp)

    if inp in words:  
        print "Yes,", inp, "is in the word!"
        new = ""
        for i in range(len(words)):
            if inp == words[i]:
                new += inp
            else:
                new += so_far[i]
        so_far = new

    else:
        print "Sorry,", inp, "isn't in the word."
        wrong += 1

if (wrong == max_wrong):
    print hangman[wrong]
    print "\nYou've been hanged!"
else:
    print "\nYou guessed it!"

print "\nThe word was", words
\$\endgroup\$
3
\$\begingroup\$

password = "python".upper() is redundant, you can just type in "PYTHON".

You should keep the whole list, in case you want to do another choice. And instead store your random choice as word. You also don't need to use str, as a file is read as a string by default. Likewise you don't need to specify 'r' for open, as it's the default there too.

words = open("word.txt", "r").read().split()
word = random.choice(words).upper()

You can manually add newline characters (\n) to print to change this

print " "
print "-----Welcome to HANGMAN, You get seven chances to guess the mystery word-----"
print " "

into this

print "\n-----Welcome to HANGMAN, You get seven chances to guess the mystery word-----\n"

Also I recommend rearranging the start to declare all the constants together. Then get words and word all before priting the welcome message. You can also put them all inside an initialising function, that way you can easier restart a new game.
Like this:

def init():
    wrong = 0
    used = []
    password = "python".upper()
    max_wrong = len(hangman) - 1
    so_far = "*" * len(words)   

    words = open("word.txt", "r").read().split()
    word = random.choice(words).upper()

    print "\n-----Welcome to HANGMAN, You get seven chances to guess the mystery word-----\n"
    print "You need to guess", len(words), "letters word"

You should use whitespace to group stuff together based on what stuff actually fits together:

so_far = "*" * len(words)   
print "You need to guess", len(words), "letters word"
while wrong < max_wrong and so_far != words:


    print hangman[wrong]

This makes it hard to notice that there's a while loop at first. This would be better:

so_far = "*" * len(words)   
print "You need to guess", len(words), "letters word"

while wrong < max_wrong and so_far != words:
    print hangman[wrong]

For reading input, I'd put it in its own function separate and have it loop until there's a valid input.

def enter_letter(used):
    """Loop until the user enters a valid letter"""

    while True:
        inp = raw_input("Pick a letter----->").upper()

I would also add .strip() to the end, to remove any accidental whitespace the user might enter. It will remove any whitespace characters from the start or end of the string.

        if inp.isdigit() is True=:
            print "Invalid Input"
            continue

Note, you don't need is True, it's being evaluated as a boolean anyway and I'd put all invalid checks in one if statement.

        if not inp.isalpha() or inp.isdigit() or len(inp) != 1:

In your script, you didn't check for an empty input, you should only accept something that is exactly 1 character.

Now you could run your check to see if the letter is already used.

        if inp in used:
            print "You've already guessed the letter:", inp
            continue

So back in the main game loop, it will actually just look like this:

    inp = enter_letter(used)
    used.append(inp)

And then you can check if it's in the word or not.

This is kind of unnecessary, you can use a for loop with enumerate to get both the index and value of the string at the same time rather than needing to index each time:

    for i, char in enumerate(words):
        if inp == char:
            new += inp
        else:
            new += so_far[i]

Since you tagged beginner I wont go deep into it (unless you ask) but you could look into list comprehensions for a way to make this happen in one line. It's basically a way to condense a for loop into a single line to create a list. They're handy but can be confusing. If you want me to explain it here, please comment and I'll edit it in.


I would also recommend that you try to put code in functions more. For example, you could put the end game in a function. The main game loop could be too. They wouldn't add a lot to the current script but they would make it easier to expand or reuse. What if you want different kinds of hangman games, or rules? Separating out parts of how the code operates makes it easier to swap in another one or make changes to a function you're using.

\$\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.