a simple hangman game in python

D33wakar 1 Tallied Votes 709 Views Share

This is a simple hangman game that I wrote using my beginner python skills. Though this game is playable, there must be lots of things I must've been doing wrong or the methods I'm using here may be not so pythonic. So I want some suggestions on how to improve this game.
The 'wordsdict.pkl' file contains a pickled dict with words as keys and meanings as their values.

e.g. {'word': 'its meaning'}
#!/usr/bin/env python

import random 
import cPickle 

class Hangman(object):
    '''A simple hangman game that tries to improve your vocabulary a bit '''
    def __init__(self):
        # the variables used, this is not necessary
        self.dumpfile = ''       #the dictionary file
        self.dictionary = {}     #the pickled dict
        self.words = []          #list of words used
        self.secret_word = ''    #the 'key'
        self.length = 0          #length of the 'key'
        self.keys = []           #inputs that match the 'key'
        self.used_keys = []      #keys that are already used
        self.guess = ''          #player's guess
        self.mistakes = 0        #number of incorrect inputs
        
        return self.load_dict()
        
    #insert some random hints for the player
    def insert_random(self, length):
        randint = random.randint
        
        # 3 hints
        if length >= 7: hint = 3
        else: hint = 1
        for x in xrange(hint):
                a = randint(1, length - 1)
                self.keys[a-1] = self.secret_word[a-1]

    def test_input(self):
        #if the guessed letter matches
        if self.guess in self.secret_word:
            indexes = [i for i, item in enumerate(self.secret_word) if item == self.guess]
            for index in indexes:
                self.keys[index] = self.guess
                self.used_keys.append(self.guess)
                print "used letters ",set(self.used_keys),'\n'
       
        #if the guessed letter didn't match
        else:
            self.used_keys.append(self.guess)
            self.mistakes += 1
            print "used letters ",set(self.used_keys),'\n'
    

    # load the pickled word dictionary and unpickle them    
    def load_dict(self):
        try :
            self.dumpfile = open("~/python/hangman/wordsdict.pkl", "r")
        except IOError:
            print "Couldn't find the file 'wordsdict.pkl'"
            quit()
        self.dictionary = cPickle.load(self.dumpfile)
        self.words = self.dictionary.keys()
        self.dumpfile.close()
        return self.prepare_word()
    
    #randomly choose a word for the challenge
    def prepare_word(self):
        
        self.secret_word = random.choice(self.words)
        #don't count trailing spaces
        self.length = len(self.secret_word.rstrip())
        self.keys = ['_' for x in xrange(self.length)]
        self.insert_random(self.length)
        return self.ask()

    #display the challenge
    def ask(self):
        print ' '.join(self.keys), ":", self.dictionary[self.secret_word] 
        print 
        return self.input_loop()

    #take input from the player
    def input_loop(self):
        #four self.mistakes are allowed
        chances = len(set(self.secret_word)) + 4          
        while chances != 0 and self.mistakes < 5:
            try:
                self.guess = raw_input("> ")
                
            except EOFError:
                exit(1)
            self.test_input()
            print ' '.join(self.keys)
            if '_' not in self.keys:
                print 'well done!'
                break
            chances -= 1
       
        if self.mistakes > 4: print 'the word was', ''.join(self.secret_word).upper()
        return self.quit_message()
    
    def quit_message(self):
        print "\n"
        print "Press 'c' to continue, or any other key to quit the game. "
        print "You can always quit the game by pressing 'Ctrl+D'"
        try:
            command = raw_input('> ')
            if command == 'c': return self.__init__() #loopback
            else : exit(0)
        except EOFError: exit(1)
            
        
        
        


if __name__ == '__main__':
    game = Hangman()
    game.__init__()
TrustyTony 888 pyMod Team Colleague Featured Poster

You do not call __init__ explicitely like you do at line 113, and it has no return value, but the returned value is the object created. You are not using the game instance to anything, so why the class?

You are doing strange chain of action from __init__ return through each methods return, which is very bizare for me. why not just do the sequence of calls in main program?

Without the pickled dictionary I can not run the program so that is how far I can comment now (zipped and attached File would help).

D33wakar 36 Posting Whiz in Training

Without the picled dictionary I can not run the program so that is how far I can comment now (zipped and attached File would help).

That was a serious mistake on my part.

D33wakar 36 Posting Whiz in Training

You are doing strange chain of action from init return through each methods return, which is very bizare for me. why not just do the sequence of calls in main program?

This is the same program without the class.

#!/usr/bin/env python

import random 
import cPickle

#path of the dump file
filepath = '/home/deewakar/python/hangman/wordsdict.pkl'

#inset some random hints for the player
def insert_hints(length, keylist, secret_word):
    randint = random.randint
    #if the word contains 7 or more letters, you'll get 3 hints
    if length >= 7: hints = 3
    else: hints = 1
    for x in xrange(hints):
        a = randint(1, length - 1)
        keylist[a-1] = secret_word[a-1]

    return hints, keylist

def test_input(guess, secret_word, keylist, mistakes, used_keys ):
    #if the guessed letter matches
    if guess in secret_word:
        indexes = [i for i, item in enumerate(secret_word) if item == guess]
        for index in indexes:
            keylist[index] = guess
            used_keys.append(guess)

    #if the guessed letter didn't match
    else:
        used_keys.append(guess)
        mistakes += 1
    print "used letters ",set(used_keys),'\n'


    return keylist, mistakes


#load the pickled word dictionary
def load_dict():
    try :
        dumpfile = open(filepath, "r")
    except IOError:
        print "Couldn't open the dictionary file 'wordsdict.pkl'"
        quit()

    dictionary = cPickle.load(dumpfile)
    words = dictionary.keys()
    return dumpfile, dictionary, words

#randomly choose a word for the challenge
def prepare_word(words):
    secret_word = random.choice(words)
    #don't count trailing spaces
    length = len(secret_word.rstrip())
    keylist = ['_' for x in xrange(length)]
    hints, keylist = insert_hints(length, keylist, secret_word)
    return secret_word, keylist, hints

#display the challenge
def ask(keylist, secret_word, dictionary):
    print ' '.join(keylist), ":", dictionary[secret_word] 

#take input from the player
def input_loop(secret_word, mistakes, keylist):
        #four mistakes are allowed
        chances = len(set(secret_word)) + 4

        #letters that are already used by the player
        used_keys = []
        while chances != 0 and mistakes < 5:
            try:
                guess = raw_input("> ")

            except EOFError:
                return 'quit'
            keylist, mistakes = test_input(guess, secret_word, keylist, mistakes, used_keys)
            print ' '.join(keylist)
            if '_' not in keylist:
                print 'well done!'
                break
            chances -= 1

        if mistakes > 4: print 'the word was', ''.join(secret_word).upper()

def quit_msg(dumpfile):
    print "\n"
    print "Press 'c' to continue, or any other key to quit the game. "
    print "You can always quit the game by pressing 'Ctrl+D'"
    try:
        command = raw_input('> ')
        if command == 'c': main() #loopback
        else :
            dumpfile.close()
            exit()

    except EOFError:
        dumpfile.close()
        exit()

def quit_game(dumpfile):
    dumpfile.close()
    exit()

#the main program loop
def main():
    mistakes = 0          #count of mistakes made by the player

    #open the dump file and load the pickcled dictionary
    dumpfile, dictionary, words = load_dict()

    #choose a random word from the list and spray it with some hints
    secret_word, keylist, hints = prepare_word(words)

    #display the challenge
    ask(keylist, secret_word, dictionary)

    #take the player's inputs
    signal = input_loop(secret_word, mistakes, keylist)

    if signal == 'quit':
        dumpfile.close()
        exit()
    else:
        #the message displayed after the game
        quit_msg(dumpfile)



if __name__ == '__main__': main()
TrustyTony 888 pyMod Team Colleague Featured Poster

My variation, I could not do cradual change, so this is basically my coding. It is changed so that it works also with Python3 (raw_input, cPickle with protocol and encoding)

#!/usr/bin/env python

import random 

try:
    import cPickle
    input = raw_input
except:
    import pickle

try:
    with open("wordsdict.pkl", 'rb') as dumpfile:
        if 'cPickle' in globals():
            dictionary = cPickle.load(dumpfile)
        else:
            dictionary = pickle.load(dumpfile, encoding ='latin1')

    secret_letters, max_guess = 4, 7
    while True:
        secret_word = random.choice(list(dictionary.keys()))
        print('Hint: %s' % dictionary[secret_word])
        #print(secret_word)
        unique = set(secret_word)
        secret_word = secret_word.rstrip()
        chosen = set(random.sample(unique, len(unique) - secret_letters))

        for mistakes in range(max_guess):
            inp = ''
            while len(inp) != 1 and len(inp) != len(secret_word) or inp in chosen:
                print(' '.join('_' if c not in chosen else c for c in secret_word))
                inp = input("%i: single letter or whole word: " % (mistakes + 1))

            if len(inp) == 1:
                chosen.add(inp)
            if inp == secret_word or all(c in chosen for c in secret_word):
                print('You found it!')
                break

        print('The word was %s.' % secret_word.upper())

        print("\n")
        print("Press 'c' to continue, or any other key to quit the game. ")
        print("You can always quit the game by pressing 'Ctrl+D'")
        inp = input("> ") 
        if inp.lower() != 'c':
            raise EOFError
except EOFError:
    print('\nBye!\n')
except IOError as e:
    print('Dump file failed: %s' % e)
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.