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.

Note: The code works on both Python 3 and 2.

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()
Peilonrayz
44.4k7 gold badges80 silver badges157 bronze badges
asked Mar 26, 2017 at 17:13
\$\endgroup\$
1
  • \$\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\$ Commented Apr 15, 2017 at 18:17

2 Answers 2

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.
answered Mar 26, 2017 at 21:49
\$\endgroup\$
1
  • \$\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\$ Commented Apr 7, 2017 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)
answered Mar 28, 2017 at 21:23
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.