2
\$\begingroup\$

I know that some features overlap but this is because I added different functions to the code at different stages when I thought of them.

import random,sys

Hangman = ['''
   +---+
       |
       |
       |
       |
       |
 =========''','''

   +---+
   |   |
       |
       |
       |
       |
 =========''', '''

   +---+
   |   |
   O   |
       |
       |
       |
 =========''', '''

   +---+
   |   |
   O   |
   |   |
       |
       |
 =========''', '''

   +---+
   |   |
   O   |
  /|   |
       |
       |
 =========''', '''

   +---+
   |   |
   O   |
  /|\  |
       |
       |
 =========''', '''

   +---+
   |   |
   O   |
  /|\  |
  /    |
       |
 =========''', '''

   +---+
   |   |
   O   |
  /|\  |
  / \  |
       |
 =========''']

words = 'ant baboon badger bat bear beaver camel cat clam cobra cougar coyote crow deer dog donkey duck eagle ferret fox frog goat goose hawk lion lizard llama mole monkey moose mouse mule newt otter owl panda parrot pigeon python rabbit ram rat raven rhino salmon seal shark sheep skunk sloth snake spider stork swan tiger toad trout turkey turtle weasel whale wolf wombat zebra'.split()

def menu():
    pass

def cpuPlays():
    pass


def GetRandomWord(word):
    chosenWord = random.choice(word)
    return chosenWord


def wordLength(word,wordList):
    userEntury = input("Would you like Tier 1 or Tier 2 words? (1 or 2):")
    if userEntury == '1':
        index = wordList.index(word)
        index-=1
        if len(word) >= 5:
            #print(word,'1')
            return word
        else:
            for n in range(len(wordList)):
                index+=1 
                if len(wordList[index]) >= 5:
                    word = wordList[index]
                    #print(word,'2')
                    return word
                elif len(wordList) == index: 
                    index = len(wordList) - index  
                    while len(wordList[index])<5:
                        index +=1
                        if len(wordList[index]) >= 5:
                            word = wordList[index]
                            #print(word,'3')
                            return word



    elif userEntury == '2':
        index = wordList.index(word)
        index-=1
        if len(word) <= 4:
            #print(word,'1')
            return word
        else:
            for n in range(len(wordList)):
                index+=1
                if len(wordList[index]) <= 4:
                    word = wordList[index]
                    #print(word,'2')
                    return word
                elif len(wordList) == index: 
                    index = len(wordList) - index
                    while len(wordList[index])>4:
                        index +=1
                        if len(wordList[index]) <=4:
                            word = wordList[index]
                            #print(word,'3')
                            return word




def display(hangmanPic,secretWord,numWrongLetters,correctLetters):
    blanks = ['-']*len(secretWord) # makes list of strings instead of putting all into one string

    for i in range(len(secretWord)):#repleaces blank letters with correct letters
        if secretWord[i] in correctLetters:
             blanks[i] = secretWord[i] #looks through each string and changes it if needed

    print("Missing Letters:")        
    for letter in blanks:
        print(letter,end='')
    print(hangmanPic[numWrongLetters])



def getGuess(alreadyGuessed):
    while True:
        print("Guess Letter:")
        guess = input()
        guess = guess.lower()
        if len(guess) != 1:
            print("Please enter only 1 letter.")
        elif guess in alreadyGuessed:
            print("Letter is already guessed.")
        elif guess.isdigit():
            print("Please enter a letter not integer.")
        else:
            return guess

def playAgain():
    print("Do you want to play again?(yes or no)") 
    return input().lower().startswith('y')



print("H A N G M A N")

correctLetters = ''
guessedLetters = ''
wrongLetters = 0
randomWord = GetRandomWord(words)
#print(randomWord)
gameDone = False
GameIsRunning = True
WordLength = wordLength(randomWord,words)

while GameIsRunning:

    display(Hangman,WordLength,wrongLetters,correctLetters)
    guess = getGuess(correctLetters + guessedLetters)

    if guess in randomWord:
        correctLetters += guess

        #Checks if player has won
        foundAllLetters = True
        for i in range(len(randomWord)):
            if randomWord[i] not in correctLetters:
                foundAllLetters = False
                break
        if randomWord[i] in correctLetters:
            foundAllLetters = True
            print("Well Done You found what the missing word is!")
            gameDone = True

    else:
        wrongLetters +=1
        guessedLetters += guess

        #Check if player has lost

        if wrongLetters == len(Hangman)-1:
            print(Hangman[7])
            print("""You have ran out of guesses the word was %s. You had %d correct guess(es) out of %d in total.
                  """ % (randomWord,len(correctLetters),len(Hangman)))
            gameDone = True


    #Ask player to play again

    if gameDone == True:
        if playAgain():
            wrongLetters = 0
            guessedLetters = ''
            correctLetters = ''
            randomWord = GetRandomWord(words)
            WordLength = wordLength(randomWord,words)
            gameDone = False
        else:
            GameIsRunning = False
            exit()
\$\endgroup\$
  • \$\begingroup\$ Don't change code after answers have been given. This was not the most critical change, but in general don't change code. I rolled back the edit. \$\endgroup\$ – holroy Apr 15 '17 at 18:17
4
\$\begingroup\$

As per features:

  • It would be nice if I didn't have to press Enter after each letter. Use unbuffered input. Same goes with Tier 1/2 and Yes/No. This way, you don't even have to use the "Please enter only 1 letter" message.
  • If you don't necessarily want this to be platform-independent, you should use a curses window and clear it after each letter so the gallows will stay on top of the screen instead of repeating again and again. You could then improve by updating only those parts of screen which need updating (eg. the gallows and letters).
  • Explain what is the difference between Tier 1 and Tier 2.
  • Perhaps let the user provide a file with words to choose from. Would be simple enough to implement.

Other remarks:

  • In function wordLength, you forgot to account for invalid input. This results in a TypeError. You should print an error message and ask again.
  • Sometimes, at the end when I loose and the program prints the word, it's clearly incorrect. Eg. letters are m--- and it says the word was llama.
  • The function GetRandomWord seems pointless, it's the same as random.choice. If the argument is called words, then GetRandomWord(words) is not much more readable than random.choice(words). Although, one might argue that if you wanted to switch to another implementation of choice, it would be easier. But my guess is that wasn't your intention.
  • Create a main function and check if __name__ == '__main__'. If yes, call that main function, otherwise don't do anything. It might not be necessary in this program, but if someone else wanted to use functions from your module, they would have to import it. And when they do, your game is going to start playing, which is not what they want.
\$\endgroup\$
  • \$\begingroup\$ Thank you for the tips but ive finished with the Hangman game not gonna improve it anymore as i've worked on it way too long i want to move on to another game, right now im working on Tic Tac Toe game i'll make sure to add as many of these features as i can in to it \$\endgroup\$ – Ivan Apr 7 '17 at 13:52
3
\$\begingroup\$

Instead of for i in range(len(randomWord)): and using indexes, iterate over the items directly:

for letter in randomWord:
    if letter not in correctLetters:
        foundAllLetters = False
        break

And if you need the item and the index, enumerate will help you:

for i, letter in enumerate(secretWord):
    if letter in correctLetters:
        blanks[i] = letter

In the line if gameDone == True: you can omit the True, so just write if gameDone:.


If you have to write such long strings, you can use multiline strings (with triple quotes) to keep the line length short. Note that this will add new line characters on the right and white space on the left, if the code is indented.

words = """ant baboon badger bat bear beaver camel cat clam cobra
cougar coyote crow deer dog donkey duck eagle ferret fox frog goat
goose hawk lion lizard llama mole monkey moose mouse mule newt otter
owl panda parrot pigeon python rabbit ram rat raven rhino salmon seal
shark sheep skunk sloth snake spider stork swan tiger toad trout
turkey turtle weasel whale wolf wombat zebra""".split()

You can also write it like so (strings are concatenated automatically):

words = (
    'ant baboon badger bat bear beaver camel cat clam cobra '
    'cougar coyote crow deer dog donkey duck eagle ferret fox '
    'frog goat'.split())

Add docstrings to your functions, which explain what they do and how they should be used.


Especially the wordLength function looks a bit complicated and should be simplified. It seems its purpose is to either return long words for tier 1 and short words for tier 2.

I suggest to filter the word list (with list comprehensions) and create two new lists consisting of the long and the short words:

short_words = [word for word in words if len(word) < 5]
long_words = [word for word in words if len(word) >= 5]

Now you can just use random.choice to pick a long or short word depending on the tier value.

def pick_word(tier):
    if tier == '1':
        return random.choice(long_words)
    else:
        return random.choice(short_words)
\$\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.