from __future__ import print_function try: import Tkinter import tkMessageBox except ImportError: import tkinter as Tkinter import tkinter.messagebox as tkMessageBox class Hangman: """Play the Hangman game.""" def __init__(self, wl): """Setup hangman game using given word list.""" # Create the main game frame self.app = Tkinter.Frame() self.app.pack(expand=Tkinter.TRUE, fill=Tkinter.BOTH) # Get the "toplevel" window (basically, it's the # window that contains the main window, along with # the title bar, window management buttons, and resize # controls) and set the title top = self.app.winfo_toplevel() top.title('Hangman') # Put a "Quit" button at the bottom-center of the game quitButton = Tkinter.Button(self.app, text='Quit', command=self._quit) quitButton.pack(side=Tkinter.BOTTOM) # Put an empty frame at the top of the game. This # frame will contain the actual letters of the words. self.wordFrame = Tkinter.Frame(self.app, borderwidth=2, relief=Tkinter.SUNKEN) self.wordFrame.pack(side=Tkinter.TOP) self.wordButtons = [] # Put a label and an entry field below the word frame. # The label will show how many guesses remain, and # the entry field is where the next guess is entered. self.label = Tkinter.Label(self.app, text='Guesses:') self.label.pack(side=Tkinter.LEFT) self.entry = Tkinter.Entry(self.app) self.entry.pack(side=Tkinter.LEFT, fill=Tkinter.X) self.entry.bind('', self._guess) # Read in the list of words self.wordList = wl def startGame(self): """Setup the user interface for a new game.""" # Get a new word self.word = self.wordList.selectWord() self.guesses = 7 self.guessed = [] self.blanks = len(self.word) # Remove all the buttons for the old word for b in self.wordButtons: b.forget() # Create buttons for the new word self.wordButtons = [] for i in range(len(self.word)): b = Tkinter.Button(self.wordFrame, text=' ', width=1) b.pack(side=Tkinter.LEFT) self.wordButtons.append(b) # Display the appropriate prompt self.showPrompt() def showPrompt(self): """Display the prompt for the next guess.""" if self.guesses > 2: prompt = '%d guesses remain:' % self.guesses else: prompt = 'One guess remains:' self.label.config(text=prompt) def _guess(self, event): """Callback invoked when user hits return in entry field.""" # Make sure user made a legitimate guess. # Always erase the contents of the entry field. s = self.entry.get() self.entry.delete(0, Tkinter.END) if len(s) <= 0 or not s[0].islower(): tkMessageBox.showwarning(title='Hangman Warning', message='Guess must be a lowercase letter.') return # If he already guessed this letter before, we will # be nice and tell him. if s[0] in self.guessed: tkMessageBox.showwarning(title='Hangman Warning', message='You already guessed "%s".' % s[0]) return self.guessed.append(s[0]) # Check if the guess matched any letters. any = 0 for i in range(len(self.word)): if self.word[i] == s[0]: any = 1 self.blanks = self.blanks - 1 self.showLetter(i) # If no more blanks remain in the game, he wins. if self.blanks == 0: tkMessageBox.showinfo(title='Hangman Message', message='Congratulations!') self.startGame() return # He guessed right, so the number of guesses remaining # stays the same. if any: return # He guessed wrong, so we deduct a guess. If he # has some remaining, show that. Otherwise, show # him the word and start over. self.guesses = self.guesses - 1 if self.guesses > 0: self.showPrompt() else: for i in range(len(self.word)): self.showLetter(i) tkMessageBox.showinfo(title='Hangman Message', message='No more guesses!') self.startGame() def showLetter(self, n): """Show the n'th letter of the word.""" b = self.wordButtons[n] b.config(text=self.word[n].upper()) def play(self): """Play hangman repeatedly until user quits.""" self.startGame() self.entry.focus() self.app.mainloop() print('Bye.') def _quit(self): """Callback invoked when user clicks "Quit" button.""" self.app.quit() if __name__ == '__main__': import wordlist game = Hangman(wordlist.BigWordList('words')) game.play()