I created this version of Hangman in Python 3. Does anyone have any tips for optimization or improvement?
import random
HANGMAN = (
'''
-------+''',
'''
+
|
|
|
|
|
-------+''',
'''
-----+
|
|
|
|
|
-------+''',
'''
-----+
| |
|
|
|
|
-------+''',
'''
-----+
| |
O |
|
|
|
-------+''',
'''
-----+
| |
O |
| |
|
|
-------+''',
'''
-----+
| |
O |
/| |
|
|
-------+''',
'''
-----+
| |
O |
/|\ |
|
|
-------+''',
'''
-----+
| |
O |
/|\ |
/ |
|
-------+''',
'''
-----+
| |
O |
/|\ |
/ \ |
|
-------+''')
MAX = len(HANGMAN) - 1
WORDS = ('jazz', 'buzz', 'hajj', 'fuzz', 'jinx', 'jazzy', 'fuzzy', 'faffs', 'fizzy', 'jiffs', 'jazzed', 'buzzed', 'jazzes', 'faffed', 'fizzed', 'jazzing', 'buzzing', 'jazzier', 'faffing', 'fuzzing')
sizeHangman = 0
word = random.choice(WORDS)
hiddenWord = list('-' * len(word))
lettersGuessed = []
print('\tHANGMAN GAME\n\t\tBy Lewis Cornwall\n')
while sizeHangman < MAX:
print('This is your hangman:' + HANGMAN[sizeHangman] + '\nThis is the word:\n' + ''.join(hiddenWord) + '\nThese are the letters you\'ve already guessed:\n' + str(lettersGuessed))
guess = input('Guess a letter: ').lower()
while guess in lettersGuessed:
print('You\'ve already guessed that letter!')
guess = input('Guess a letter: ').lower()
if guess in word:
print('Well done, "' + guess + '" is in my word!')
for i in range(len(word)):
if guess == word[i]:
hiddenWord[i] = guess
if hiddenWord.count('-') == 0:
print('Congratulations! My word was ' + word + '!')
input('Press <enter> to close.')
quit()
else:
print('Unfortunately, "' + guess + '" is not in my word.')
sizeHangman += 1
lettersGuessed.append(guess)
print('This is your hangman: ' + HANGMAN[sizeHangman] + 'You\'ve been hanged! My word was actually ' + word + '.')
input('Press <enter> to close.')
-
2\$\begingroup\$ Not an optimization, but you could load your words from a - possibly encrypted - text file instead of having them in your raw code :) \$\endgroup\$Morwenn– Morwenn2013年03月11日 13:22:45 +00:00Commented Mar 11, 2013 at 13:22
3 Answers 3
You can avoid repeating guess = input('Guess a letter: ').lower()
by changing the inner while loop to:
while True:
guess = input('Guess a letter: ').lower()
if guess in lettersGuessed:
print('You\'ve already guessed that letter!')
else:
break
Instead of for i in range(len(word))
use:
for i, letter in enumerate(word):
You could also avoid indexing by i
altogether by using a list comprehension. I'm not sure if this is as clear in this case, though.
hiddenWord = [guess if guess == letter else hidden for letter, hidden in zip(word, hiddenWord)]
Instead of hiddenWord.count('-') == 0
use:
'-' not in hiddenWord
The docs say quit()
should not be used in programs. Your count('-') == 0
check is unnecessarily inside the for i
loop. If you move it after the loop, you could use break
to exit the main loop. You could add an else
clause to the main with
statement for dealing with the "You've been hanged" case. The main loop becomes:
while sizeHangman < MAX:
print('This is your hangman:' + HANGMAN[sizeHangman] + '\nThis is the word:\n' + ''.join(hiddenWord) + '\nThese are the letters you\'ve already guessed:\n' + str(lettersGuessed))
while True:
guess = input('Guess a letter: ').lower()
if guess in lettersGuessed:
print('You\'ve already guessed that letter!')
else:
break
if guess in word:
print('Well done, "' + guess + '" is in my word!')
for i, letter in enumerate(word):
if guess == letter:
hiddenWord[i] = guess
if '-' not in hiddenWord:
print('Congratulations! My word was ' + word + '!')
break
else:
print('Unfortunately, "' + guess + '" is not in my word.')
sizeHangman += 1
lettersGuessed.append(guess)
else:
print('This is your hangman: ' + HANGMAN[sizeHangman] + 'You\'ve been hanged! My word was actually ' + word + '.')
input('Press <enter> to close.')
Some ideas:
You might want to make sure that the guess is actually a single letter.
lettersGuessed
should be a set, so membership tests (guess in lettersGuessed
) is a constant time operation.Similarly, you could store either the (correctly) guessed letters or the letters that still have to be (correctly) guessed in a set. For example:
word = random.choice(WORDS) requiredGuesses = set(word) lettersGuessed = set() # then later if guess in lettersGuessed: print('You already guessed this') elif guess in requiredGuesses: print('Correct guess!') requiredGuesses.remove(guess) lettersGuessed.add(guess) else: print('Incorrect guess')
This also makes the test if the whole word was guessed easier:
if not requiredGuesses: print('You found the word')
Instead of keeping a
hiddenWord
which you keep adjusting whenever a correct guess is made, you could just create the hidden output on the fly:print(''.join('-' if l in requiredGuesses else l for l in word))
You might want to add a class for this game that encapsulates some of the game logic.
You should implement the ability to read words from a txt document. This can be done by:
f = open("wordlist.txt", 'w')
word_list.append(f.readlines())
this would allow you to have far bigger lists to choose from.
Explore related questions
See similar questions with these tags.