hangman.py

来自「Wxpython Implemented on Windows CE, Sou」· Python 代码 · 共 472 行 · 第 1/2 页

PY
472
字号
"""Hangman.py, a simple wxPython game, inspired by the
old bsd game by Ken Arnold.
>From the original man page:

 In hangman, the computer picks a word from the on-line
 word list and you must try to guess it.  The computer
 keeps track of which letters have been guessed and how
 many wrong guesses you have made on the screen in a
 graphic fashion.

That says it all, doesn't it?

Have fun with it,

Harm van der Heijden (H.v.d.Heijden@phys.tue.nl)"""

import random,re
import wx


class WordFetcher:
    builtin_words = ' albatros  banana  electrometer  eggshell'

    def __init__(self, filename, min_length = 5):
        self.min_length = min_length
        print "Trying to open file %s" % (filename,)
        try:
            f = open(filename, "r")
        except:
            print "Couldn't open dictionary file %s, using builtins" % (filename,)
            self.words = self.builtin_words
            self.filename = None
            return
        self.words = f.read()
        self.filename = filename
        print "Got %d bytes." % (len(self.words),)

    def SetMinLength(min_length):
        self.min_length = min_length

    def Get(self):
        reg = re.compile('\s+([a-zA-Z]+)\s+')
        n = 50 # safety valve; maximum number of tries to find a suitable word
        while n:
            index = int(random.random()*len(self.words))
            m = reg.search(self.words[index:])
            if m and len(m.groups()[0]) >= self.min_length: break
            n = n - 1
        if n: return m.groups()[0].lower()
        return "error"



def stdprint(x):
    print x



class URLWordFetcher(WordFetcher):
    def __init__(self, url):
        self.OpenURL(url)
        WordFetcher.__init__(self, "hangman_dict.txt")

    def logprint(self,x):
        print x

    def RetrieveAsFile(self, host, path=''):
        from httplib import HTTP
        try:
            h = HTTP(host)
        except:
            self.logprint("Failed to create HTTP connection to %s... is the network available?" % (host))
            return None
        h.putrequest('GET',path)
        h.putheader('Accept','text/html')
        h.putheader('Accept','text/plain')
        h.endheaders()
        errcode, errmsg, headers = h.getreply()
        if errcode != 200:
            self.logprint("HTTP error code %d: %s" % (errcode, errmsg))
            return None
        f = h.getfile()
        return f

    def OpenURL(self,url):
        from htmllib import HTMLParser
        import formatter
        self.url = url
        m = re.match('http://([^/]+)(/\S*)\s*', url)
        if m:
            host = m.groups()[0]
            path = m.groups()[1]
        else:
            m = re.match('http://(\S+)\s*', url)
            if not m:
                # Invalid URL
                self.logprint("Invalid or unsupported URL: %s" % (url))
                return
            host = m.groups()[0]
            path = ''
        f = self.RetrieveAsFile(host,path)
        if not f:
            self.logprint("Could not open %s" % (url))
            return
        self.logprint("Receiving data...")
        data = f.read()
        tmp = open('hangman_dict.txt','w')
        fmt = formatter.AbstractFormatter(formatter.DumbWriter(tmp))
        p = HTMLParser(fmt)
        self.logprint("Parsing data...")
        p.feed(data)
        p.close()
        tmp.close()



class HangmanWnd(wx.Window):
    def __init__(self, parent, id, pos=wx.DefaultPosition, size=wx.DefaultSize):
        wx.Window.__init__(self, parent, id, pos, size)
        self.SetBackgroundColour(wx.NamedColour('white'))
        if wx.Platform == '__WXGTK__':
            self.font = wx.Font(12, wx.MODERN, wx.NORMAL, wx.NORMAL)
        else:
            self.font = wx.Font(10, wx.MODERN, wx.NORMAL, wx.NORMAL)
        self.SetFocus()
        self.Bind(wx.EVT_PAINT, self.OnPaint)
        self.Bind(wx.EVT_SIZE, self.OnSize)

    def OnSize(self, event):
        self.Refresh()
        
    def StartGame(self, word):
        self.word = word
        self.guess = []
        self.tries = 0
        self.misses = 0
        self.Draw()

    def EndGame(self):
        self.misses = 7;
        self.guess = map(chr, range(ord('a'),ord('z')+1))
        self.Draw()

    def HandleKey(self, key):
        self.message = ""
        if self.guess.count(key):
            self.message = 'Already guessed %s' % (key,)
            return 0
        self.guess.append(key)
        self.guess.sort()
        self.tries = self.tries+1
        if not key in self.word:
            self.misses = self.misses+1
        if self.misses == 7:
            self.EndGame()
            return 1
        has_won = 1
        for letter in self.word:
            if not self.guess.count(letter):
                has_won = 0
                break
        if has_won:
            self.Draw()
            return 2
        self.Draw()
        return 0

    def Draw(self, dc = None):
        if not dc:
            dc = wx.ClientDC(self)
        dc.SetFont(self.font)
        dc.Clear()
        (x,y) = self.GetSizeTuple()
        x1 = x-200; y1 = 20
        for letter in self.word:
            if self.guess.count(letter):
                dc.DrawText(letter, x1, y1)
            else:
                dc.DrawText('.', x1, y1)
            x1 = x1 + 10
        x1 = x-200
        dc.DrawText("tries %d misses %d" % (self.tries,self.misses),x1,50)
        guesses = ""
        for letter in self.guess:
            guesses = guesses + letter
        dc.DrawText("guessed:", x1, 70)
        dc.DrawText(guesses[:13], x1+80, 70)
        dc.DrawText(guesses[13:], x1+80, 90)
        dc.SetUserScale(x/1000.0, y/1000.0)
        self.DrawVictim(dc)

    def DrawVictim(self, dc):
        dc.SetPen(wx.Pen(wx.NamedColour('black'), 20))
        dc.DrawLines([(10, 980), (10,900), (700,900), (700,940), (720,940),
                      (720,980), (900,980)])
        dc.DrawLines([(100,900), (100, 100), (300,100)])
        dc.DrawLine(100,200,200,100)
        if ( self.misses == 0 ): return
        dc.SetPen(wx.Pen(wx.NamedColour('blue'), 10))
        dc.DrawLine(300,100,300,200)
        if ( self.misses == 1 ): return
        dc.DrawEllipse(250,200,100,100)
        if ( self.misses == 2 ): return
        dc.DrawLine(300,300,300,600)
        if ( self.misses == 3) : return
        dc.DrawLine(300,300,250,550)
        if ( self.misses == 4) : return
        dc.DrawLine(300,300,350,550)
        if ( self.misses == 5) : return
        dc.DrawLine(300,600,350,850)
        if ( self.misses == 6) : return
        dc.DrawLine(300,600,250,850)

    def OnPaint(self, event):
        dc = wx.PaintDC(self)
        self.Draw(dc)



class HangmanDemo(HangmanWnd):
    def __init__(self, wf, parent, id, pos, size):
        HangmanWnd.__init__(self, parent, id, pos, size)
        self.StartGame("dummy")
        self.start_new = 1
        self.wf = wf
        self.delay = 500
        self.timer = self.PlayTimer(self.MakeMove)

    def MakeMove(self):
        self.timer.Stop()
        if self.start_new:
            self.StartGame(self.wf.Get())
            self.start_new = 0
            self.left = list('aaaabcdeeeeefghiiiiijklmnnnoooopqrssssttttuuuuvwxyz')
        else:
            key = self.left[int(random.random()*len(self.left))]

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?