]>
git.saurik.com Git - wxWidgets.git/blob - utils/wxPython/tests/hangman.py
ab69d3773a020e199f1890b7d6298fa39bff0ce0
1 """Hangman.py, a simple wxPython game, inspired by the old
2 bsd game by Ken Arnold.
3 From the original man page:
5 In hangman, the computer picks a word from the on-line
6 word list and you must try to guess it. The computer
7 keeps track of which letters have been guessed and how
8 many wrong guesses you have made on the screen in a
11 That says it all, doesn't it?
15 Harm van der Heijden (H.v.d.Heijden@phys.tue.nl)"""
17 import random
,re
,string
18 from wxPython
.wx
import *
21 def __init__(self
, filename
, min_length
= 5):
22 self
.min_length
= min_length
24 f
= open(filename
, "r")
26 print "Couldn't open dictionary file %s, using build-ins" % (filename
,)
27 self
.words
= self
.builtin_words
30 self
.filename
= filename
31 print "Got %d bytes." % (len(self
.words
),)
32 def SetMinLength(min_length
):
33 self
.min_length
= min_length
35 reg
= re
.compile('\s+([a-zA-Z]+)\s+')
36 n
= 50 # safety valve; maximum number of tries to find a suitable word
38 index
= int(random
.random()*len(self
.words
))
39 m
= reg
.search(self
.words
[index
:])
40 if m
and len(m
.groups()[0]) >= self
.min_length
: break
42 if n
: return string
.lower(m
.groups()[0])
44 builtin_words
= ' albatros banana electrometer eggshell'
49 class URLWordFetcher(WordFetcher
):
50 def __init__(self
, url
):
52 WordFetcher
.__init
__(self
, "hangman_dict.txt")
55 def RetrieveAsFile(self
, host
, path
=''):
56 from httplib
import HTTP
60 self
.logprint("Failed to create HTTP connection to %s... is the network available?" % (host
))
62 h
.putrequest('GET',path
)
63 h
.putheader('Accept','text/html')
64 h
.putheader('Accept','text/plain')
66 errcode
, errmsg
, headers
= h
.getreply()
68 self
.logprint("HTTP error code %d: %s" % (errcode
, errmsg
))
72 def OpenURL(self
,url
):
73 from htmllib
import HTMLParser
76 m
= re
.match('http://([^/]+)(/\S*)\s*', url
)
81 m
= re
.match('http://(\S+)\s*', url
)
84 self
.logprint("Invalid or unsupported URL: %s" % (url
))
88 f
= self
.RetrieveAsFile(host
,path
)
90 self
.logprint("Could not open %s" % (url
))
92 self
.logprint("Receiving data...")
94 tmp
= open('hangman_dict.txt','w')
95 fmt
= formatter
.AbstractFormatter(formatter
.DumbWriter(tmp
))
97 self
.logprint("Parsing data...")
102 class HangmanWnd(wxWindow
):
103 def __init__(self
, parent
, id, pos
=wxDefaultPosition
, size
=wxDefaultSize
):
104 wxWindow
.__init
__(self
, parent
, id, pos
, size
)
105 self
.SetBackgroundColour(wxNamedColour('white'))
107 def StartGame(self
, word
):
115 self
.guess
= map(chr, range(ord('a'),ord('z')+1))
117 def HandleKey(self
, key
):
119 if self
.guess
.count(key
):
120 self
.message
= 'Already guessed %s' % (key
,)
122 self
.guess
.append(key
)
124 self
.tries
= self
.tries
+1
125 if not key
in self
.word
:
126 self
.misses
= self
.misses
+1
131 for letter
in self
.word
:
132 if not self
.guess
.count(letter
):
140 def Draw(self
, dc
= None):
142 dc
= wxClientDC(self
)
144 (x
,y
) = self
.GetSizeTuple()
146 for letter
in self
.word
:
147 if self
.guess
.count(letter
):
148 dc
.DrawText(letter
, x1
, y1
)
150 dc
.DrawText('.', x1
, y1
)
153 dc
.DrawText("tries %d misses %d" % (self
.tries
,self
.misses
),x1
,50)
155 for letter
in self
.guess
:
156 guesses
= guesses
+ letter
157 dc
.DrawText("guessed:", x1
, 70)
158 dc
.DrawText(guesses
[:13], x1
+70, 70)
159 dc
.DrawText(guesses
[13:], x1
+70, 90)
160 dc
.SetUserScale(x
/1000., y
/1000.)
162 def DrawVictim(self
, dc
):
163 dc
.SetPen(wxPen(wxNamedColour('black'), 20))
164 dc
.DrawLines([(10, 980), (10,900), (700,900), (700,940), (720,940),
165 (720,980), (900,980)])
166 dc
.DrawLines([(100,900), (100, 100), (300,100)])
167 dc
.DrawLine(100,200,200,100)
168 if ( self
.misses
== 0 ): return
169 dc
.SetPen(wxPen(wxNamedColour('blue'), 10))
170 dc
.DrawLine(300,100,300,200)
171 if ( self
.misses
== 1 ): return
172 dc
.DrawEllipse(250,200,100,100)
173 if ( self
.misses
== 2 ): return
174 dc
.DrawLine(300,300,300,600)
175 if ( self
.misses
== 3) : return
176 dc
.DrawLine(300,300,250,550)
177 if ( self
.misses
== 4) : return
178 dc
.DrawLine(300,300,350,550)
179 if ( self
.misses
== 5) : return
180 dc
.DrawLine(300,600,350,850)
181 if ( self
.misses
== 6) : return
182 dc
.DrawLine(300,600,250,850)
183 def OnPaint(self
, event
):
187 class HangmanDemo(HangmanWnd
):
188 def __init__(self
, wf
, parent
, id, pos
, size
):
189 HangmanWnd
.__init
__(self
, parent
, id, pos
, size
)
190 self
.StartGame("dummy")
194 self
.timer
= self
.PlayTimer(self
.MakeMove
)
198 self
.StartGame(self
.wf
.Get())
200 self
.left
= list('aaaabcdeeeeefghiiiiijklmnnnoooopqrssssttttuuuuvwxyz')
202 key
= self
.left
[int(random
.random()*len(self
.left
))]
203 while self
.left
.count(key
): self
.left
.remove(key
)
204 self
.start_new
= self
.HandleKey(key
)
205 self
.timer
.Start(self
.delay
)
208 class PlayTimer(wxTimer
):
209 def __init__(self
,func
):
210 wxTimer
.__init
__(self
)
216 class AboutBox(wxDialog
):
217 def __init__(self
, parent
,wf
):
218 wxDialog
.__init
__(self
, parent
, -1, "About Hangman", wxDefaultPosition
, wxSize(350,450))
219 self
.wnd
= HangmanDemo(wf
, self
, -1, wxPoint(1,1), wxSize(350,150))
220 self
.static
= wxStaticText(self
, -1, __doc__
, wxPoint(1,160), wxSize(350, 250))
221 self
.button
= wxButton(self
, 2001, "OK", wxPoint(150,420), wxSize(50,-1))
222 EVT_BUTTON(self
, 2001, self
.OnOK
)
223 def OnOK(self
, event
):
225 self
.EndModal(wxID_OK
)
227 class MyFrame(wxFrame
):
228 def __init__(self
, wf
):
230 wxFrame
.__init
__(self
, NULL
, -1, "hangman", wxDefaultPosition
, wxSize(400,300))
231 self
.wnd
= HangmanWnd(self
, -1)
233 menu
.Append(1001, "New")
234 menu
.Append(1002, "End")
235 menu
.AppendSeparator()
236 menu
.Append(1003, "Reset")
237 menu
.Append(1004, "Demo...")
238 menu
.AppendSeparator()
239 menu
.Append(1005, "Exit")
240 menubar
= wxMenuBar()
241 menubar
.Append(menu
, "Game")
243 #menu.Append(1010, "Internal", "Use internal dictionary", TRUE)
244 menu
.Append(1011, "ASCII File...")
245 urls
= [ 'wxPython home', 'http://208.240.253.245/wxPython/main.html',
246 'slashdot.org', 'http://slashdot.org/',
247 'cnn.com', 'http://cnn.com',
248 'The new york Times', 'http://www.nytimes.com',
249 'De Volkskrant', 'http://www.volkskrant.nl/frameless/25000006.html']
251 for item
in range(0,len(urls
),2):
252 urlmenu
.Append(1020+item
/2, urls
[item
], urls
[item
+1])
253 menu
.AppendMenu(1012, 'URL', urlmenu
, 'Use a webpage')
254 menu
.Append(1013, 'Dump', 'Write contents to stdout')
255 menubar
.Append(menu
, "Dictionary")
257 self
.urloffset
= 1020
259 menu
.Append(1090, "About...")
260 menubar
.Append(menu
, "Help")
261 self
.SetMenuBar(menubar
)
262 self
.CreateStatusBar(2)
263 EVT_MENU(self
, 1001, self
.OnGameNew
)
264 EVT_MENU(self
, 1002, self
.OnGameEnd
)
265 EVT_MENU(self
, 1003, self
.OnGameReset
)
266 EVT_MENU(self
, 1004, self
.OnGameDemo
)
267 EVT_MENU(self
, 1005, self
.OnWindowClose
)
268 EVT_MENU(self
, 1011, self
.OnDictFile
)
269 EVT_MENU_RANGE(self
, 1020, 1020+len(urls
)/2, self
.OnDictURL
)
270 EVT_MENU(self
, 1013, self
.OnDictDump
)
271 EVT_MENU(self
, 1090, self
.OnHelpAbout
)
272 EVT_CHAR(self
.wnd
, self
.OnChar
)
274 def OnGameNew(self
, event
):
277 self
.SetStatusText("",0)
278 self
.wnd
.StartGame(word
)
279 def OnGameEnd(self
, event
):
280 self
.UpdateAverages(0)
282 self
.SetStatusText("",0)
284 def OnGameReset(self
, event
=None):
290 def OnGameDemo(self
, event
):
291 frame
= wxFrame(self
, -1, "Hangman demo", wxDefaultPosition
, self
.GetSize())
292 demo
= HangmanDemo(self
.wf
, frame
, -1, wxDefaultPosition
, wxDefaultSize
)
294 def OnDictFile(self
, event
):
295 fd
= wxFileDialog(self
)
296 if (self
.wf
.filename
):
297 fd
.SetFilename(self
.wf
.filename
)
298 if fd
.ShowModal() == wxID_OK
:
300 self
.wf
= WordFetcher(file)
301 def OnDictURL(self
, event
):
302 item
= (event
.GetId() - self
.urloffset
)*2
303 print "Trying to open %s at %s" % (self
.urls
[item
], self
.urls
[item
+1])
304 self
.wf
= URLWordFetcher(self
.urls
[item
+1])
305 def OnDictDump(self
, event
):
307 def OnHelpAbout(self
, event
):
308 about
= AboutBox(self
, self
.wf
)
310 about
.wnd
.Stop() # that damn timer won't stop!
311 def UpdateAverages(self
, has_won
):
313 self
.won
= self
.won
+ 1
314 self
.played
= self
.played
+1
315 self
.history
.append(self
.wnd
.misses
) # ugly
317 for m
in self
.history
:
319 self
.average
= float(total
/len(self
.history
))
320 def OnChar(self
, event
):
321 if not self
.in_progress
:
324 key
= event
.KeyCode();
325 if key
>= ord('A') and key
<= ord('Z'):
326 key
= key
+ ord('a') - ord('A')
328 if key
< 'a' or key
> 'z':
331 res
= self
.wnd
.HandleKey(key
)
333 self
.SetStatusText(self
.wnd
.message
)
335 self
.UpdateAverages(0)
336 self
.SetStatusText("Too bad, you're dead!",0)
340 self
.UpdateAverages(1)
341 self
.SetStatusText("Congratulations!",0)
343 percent
= (100.*self
.won
)/self
.played
346 self
.SetStatusText("p %d, w %d (%g %%), av %g" % (self
.played
,self
.won
, percent
, self
.average
),1)
348 def OnWindowClose(self
, event
):
353 print "Reading word list"
354 wf
= WordFetcher("/usr/share/games/hangman-words")
355 #wf = URLWordFetcher("http://www.tue.nl")
357 self
.SetTopWindow(frame
)
361 if __name__
== '__main__':