Python game - Hangman

Started by
5 comments, last by techguitar 12 years, 6 months ago
Hey guys

I am in my first year in university, and this is my second game program in python in 2 months of python.
I feel satisfied by this program (from what I've learnt and from my expectations)
But need some advice from all you guys.
How efficient is this program ?
Also, please advise oh how can I add a 'visual hangman' in this program.

Positive feedback is much appreciated :)



#hangman

import random #for random.choice
dictionary=['COMPUTER', 'LAPTOP', 'IDEAS', 'NANYANG', 'COLLEGE']
word=random.choice(dictionary)
original=list(word)
temp=list(word)
guess=[] #null list
trial=int(0) #for keeping track of guessess
userinput=''
counter=int(0) #keeping track of position of element in list (if found)

for i in range(len(original)): #creating the '_ _**....' list
if (original=='A') or (original=='E') or (original=='I') or (original=='O') or (original=='U'):
guess.append("*") #* for vowels
else:
guess.append("_")#_ for all other alphabets

print guess

while trial<9:
userinput=str.upper(raw_input('Input : '))

if len(userinput)>1: #checking for multiple characters
print 'Error : Input only a single character'
continue

if userinput in original:

while userinput in temp: #loop for checking redundant characters
counter=temp.index(userinput)
guess[counter]=userinput
temp.remove(userinput)
temp.insert(counter,'_')

counter=0

for i in range(0,len(temp)): #checking for final guess match with original
if temp=='_':
counter+=1

if counter==len(original): #if guess matches original
print 'Correct\t', guess
print 'You Win !'
trial=10
break

print 'Correct\t' , guess , '\tTrials left: ', (9-trial)

else:
trial+=1
print 'Incorrect', '\tTrials left: ', (9-trial)
else:
print 'You Lose !'
print 'Correct answer was\t', original

Advertisement

How efficient is this program ?


First, please explain what you think "efficient" means, and why it would matter here.

Also, please advise oh how can I add a 'visual hangman' in this program.[/quote]

Try using punctuation symbols to draw it. You can have a list that stores a bunch of strings that represent the hangman at each stage, and output the appropriate one for the number of wrong guesses.
Positive feedback is much appreciated :)[/quote]

A couple of important concepts:


guess = []
for i in range(len(original)): #creating the '_ _**....' list
if (original=='A') or (original=='E') or (original=='I') or (original=='O') or (original=='U'):
guess.append("*") #* for vowels
else:
guess.append("_")#_ for all other alphabets


In Python, we iterate over a sequence by actually iterating over it. In the current code 'range' creates a list of numbers, which we then iterate over to get individual numeric indices, and then index into the original list. This is very indirect and messy, and missing the point: the same thing that lets us iterate over the 'range' list lets us iterate over the letters of 'original' directly.

That means we can simplify to:


guess = []
for letter in original:
if (letter=='A') or (letter=='E') or (letter=='I') or (letter=='O') or (letter=='U'):
guess.append("*") #* for vowels
else:
guess.append("_")#_ for all other alphabets


Next, let's clean up that conditional logic. Python has a very neat (efficient, in every sense) built-in system for looking for one of several possibilities: you can ask if the item is 'in' the list of possibilities. For most sequence types (such as lists), this checks each element of the sequence for equality and returns true if any of them match. (The looping is done internally by the implementation, and doesn't have to interpret any Python code.) For strings, it does a substring search instead; but this is functionally the same when our 'letter' is, well, a letter.

The other thing to notice is that whether or not the 'letter' is a vowel, we do the same basic sort of thing: append an item to 'guess'. So it makes sense to factor that part out: just use the 'if' logic to determine the letter, and then have only one copy of the actual appending code. This makes our code easier to understand by emphasizing the similarity in the two cases. As it happens, we don't need a branching if-else statement for this; in Python 2.5 and up, we can use an if-else expression, as seen in the next result:


guess = []
for letter in original:
# BTW: Python lets us use either single or double quotes for strings,
# and there is not a separate type for characters - they're just length-1 strings.
guess.append('*' if letter in 'AEIOU' else '_')


Are we done? No, that wouldn't be any fun :) The last step is to realize that Python already knows how to build lists by appending them in a loop. We can use a list comprehension and avoid having to walk Python through all the steps. We write code at a higher level of abstraction (and again, the looping gets done internally). It works like this: instead of explaining the process of building the list, we simply describe its contents, as a function of the input elements. (There is also an option to 'filter' some of the input and not generate output for it, but we don't need that here.) Finally we get:


guess = [('*' if letter in 'AEIOU' else '_') for letter in original]
A tiny side note just to remember when coding in python - variables that are assigned integers do not need the integer type specified; Python defaults all integer references as regular integers, so you don't have to say 'variable = int(number)', you can just say 'variable = number'. If you add a decimal at the end of the number, it converts to a float.

Also, your question, "how efficient is this program" - very efficient. Could it be more efficient? Yes. Does it need to be? No. It's a very simple script and I'm pretty sure a 33 mHz computer with 8 mb of ram on Windows 95 would execute this program with an almost unnoticeable difference in performance than with a 6-core 3.4Ghz/16 GB ram machine.

-Adam
Lastly, if you really want to know where the slow points are, get a python profiler that profiles line-by-line (there probably is one, but don't quote me in that - I have only a little familiarity with Python).
Thank you all for your replies !

Special thanks to Zahlman for that comprehensive reply !
Really helped a lot !

Please keep them coming ! :)
I'm a programming newbie. But, I thought I'd add some non-programming advice.

When you start the program, you're confronted with some funny-looking symbols an a command line: "input." The user isn't even told they are playing hangman. You might say something like, print "Welcome to Hangman! Guess a letter. You have X wrong guesses. If you guess all the letters in the word before your guesses run out, you win!"

Also, were you looking for ASCII art? Here is a very simple hangman (the white space will display incorrectly):


SECRET WORD
_________
|/ |
| (_)
| /|\
| |
| / \
|
|___
HANGMAN


When we were kids, you had seven guesses, one for each letter of hangman. We'd draw the rope/noose, head, body, left arm, right arm, left leg, right leg and write each letter of hangman under the gallows for each wrong guess.
A 30-year-old interested in learning to program by making an old-school, simple, text-only or 2D dungeon fantasy video game.

  • As of 9/28/2011, currently attempting to learn the basics of Python 2.7.
  • As of 10/14/11, Dabbling in C#.
  • As of 10/24/11, decisively surpassed my small knowledge of Python in C#.
^^ Thanks !
Will do that !

This topic is closed to new replies.

Advertisement