<span id="7ztzv"></span>
<sub id="7ztzv"></sub>

<span id="7ztzv"></span><form id="7ztzv"></form>

<span id="7ztzv"></span>

        <address id="7ztzv"></address>

            習題 41: 來自 Percal 25 號行星的哥頓人(Gothons)?

            你在上一節中發現 dict 的秘密功能了嗎?你可以解釋給自己嗎?讓我來給你解釋一下,順便和你自己的理解對比看有什么不同。這里是我們要討論的代碼:

            cities['_find'] = find_city
            city_found = cities['_find'](cities, state)
            

            你要記住一個函數也可以作為一個變量,``def find_city`` 比如這一句創建了一個你可以在任何地方都能使用的變量。在這段代碼里,我們首先把函數 find_city 放到叫做 cities 的字典中,并將其標記為 '_find'。 這和我們將州和市關聯起來的代碼做的事情一樣,只不過我們在這里放了一個函數的名稱。

            好了,所以一旦我們知道 find_city 是在字典中 _find 的位置,這就意味著我們可以去調用它。第二行代碼可以分解成如下步驟:

            1. Python 看到 city_found = 于是知道了需要創建一個變量。
            2. 然后它讀到 cities ,然后知道了它是一個字典
            3. 然后看到了 ['_find'] ,于是 Python 就從索引找到了字典 cities 中對應的位置,并且獲取了該位置的內容。
            4. ['_find'] 這個位置的內容是我們的函數 find_city ,所以 Python 就知道了這里表示一個函數,于是當它碰到 ( 就開始了函數調用。
            5. cities, state 這兩個參數將被傳遞到函數 find_city 中,然后這個函數就被運行了。
            6. find_city 接著從 cities 中尋找 states ,并且返回它找到的內容,如果什么都沒找到,就返回一個信息說它什么都沒找到。
            7. Python find_city 接受返回的信息,最后將該信息賦值給一開始的 city_found 這個變量。

            我再教你一個小技巧。如果你倒著閱讀的話,代碼可能會變得更容易理解。讓我們來試一下,一樣是那行:

            1. statecity 是...
            2. 作為參數傳遞給...
            3. 一個函數,位置在...
            4. '_find' 然后尋找,目的地為...
            5. cities 這個位置...
            6. 最后賦值給 city_found.

            還有一種方法讀它,這回是“由里向外”。

            1. 找到表達式的中心位置,此次為 ['_find'].
            2. 逆時針追溯,首先看到的是一個叫 cities 的字典,這樣就知道了 cities 中的 _find 元素。
            3. 上一步得到一個函數。繼續逆時針尋找,看到的是參數。
            4. 參數傳遞給函數后,函數會返回一個值。然后再逆時針尋找。
            5. 最后,我們到了 city_found = 的賦值位置,并且得到了最終結果。

            數十年的編程下來,我在讀代碼的過程中已經用不到上面的三種方法了。我只要瞟一眼就能知道它的意思。甚至給我一整頁的代碼,我也可以一眼瞄出里邊的 bug 和錯誤。這樣的技能是花了超乎常人的時間和精力才鍛煉得來的。在磨練的過程中,我學會了下面三種讀代碼的方法,它們適用于幾乎所有的編程語言:

            1. 從前向后。
            2. 從后向前。
            3. 逆時針方向。

            下次碰到難懂的語句時,你可以試試這三種方法。

            現在我們來寫這次的練習,寫完后再過一遍,這節習題其實挺有趣的。

              1
              2
              3
              4
              5
              6
              7
              8
              9
             10
             11
             12
             13
             14
             15
             16
             17
             18
             19
             20
             21
             22
             23
             24
             25
             26
             27
             28
             29
             30
             31
             32
             33
             34
             35
             36
             37
             38
             39
             40
             41
             42
             43
             44
             45
             46
             47
             48
             49
             50
             51
             52
             53
             54
             55
             56
             57
             58
             59
             60
             61
             62
             63
             64
             65
             66
             67
             68
             69
             70
             71
             72
             73
             74
             75
             76
             77
             78
             79
             80
             81
             82
             83
             84
             85
             86
             87
             88
             89
             90
             91
             92
             93
             94
             95
             96
             97
             98
             99
            100
            101
            102
            103
            104
            105
            106
            107
            108
            109
            110
            111
            112
            113
            114
            115
            116
            117
            118
            119
            120
            121
            122
            123
            124
            125
            126
            127
            128
            129
            130
            131
            132
            133
            134
            135
            136
            137
            138
            139
            140
            141
            142
            143
            144
            145
            146
            147
            148
            149
            150
            151
            152
            153
            154
            155
            156
            157
            158
            159
            160
            161
            162
            163
            164
            165
            166
            167
            168
            from sys import exit
            from random import randint
            
            def death():
                quips = ["You died.  You kinda suck at this.",
                         "Nice job, you died ...jackass.",
                         "Such a luser.",
                         "I have a small puppy that's better at this."]
            
                print quips[randint(0, len(quips)-1)]
                exit(1)
            
            
            def central_corridor():
                print "The Gothons of Planet Percal #25 have invaded your ship and destroyed"
                print "your entire crew.  You are the last surviving member and your last"
                print "mission is to get the neutron destruct bomb from the Weapons Armory,"
                print "put it in the bridge, and blow the ship up after getting into an "
                print "escape pod."
                print "\n"
                print "You're running down the central corridor to the Weapons Armory when"
                print "a Gothon jumps out, red scaly skin, dark grimy teeth, and evil clown costume"
                print "flowing around his hate filled body.  He's blocking the door to the"
                print "Armory and about to pull a weapon to blast you."
            
                action = raw_input("> ")
            
                if action == "shoot!":
                    print "Quick on the draw you yank out your blaster and fire it at the Gothon."
                    print "His clown costume is flowing and moving around his body, which throws"
                    print "off your aim.  Your laser hits his costume but misses him entirely.  This"
                    print "completely ruins his brand new costume his mother bought him, which"
                    print "makes him fly into an insane rage and blast you repeatedly in the face until"
                    print "you are dead.  Then he eats you."
                    return 'death'
            
                elif action == "dodge!":
                    print "Like a world class boxer you dodge, weave, slip and slide right"
                    print "as the Gothon's blaster cranks a laser past your head."
                    print "In the middle of your artful dodge your foot slips and you"
                    print "bang your head on the metal wall and pass out."
                    print "You wake up shortly after only to die as the Gothon stomps on"
                    print "your head and eats you."
                    return 'death'
            
                elif action == "tell a joke":
                    print "Lucky for you they made you learn Gothon insults in the academy."
                    print "You tell the one Gothon joke you know:"
                    print "Lbhe zbgure vf fb sng, jura fur fvgf nebhaq gur ubhfr, fur fvgf nebhaq gur ubhfr."
                    print "The Gothon stops, tries not to laugh, then busts out laughing and can't move."
                    print "While he's laughing you run up and shoot him square in the head"
                    print "putting him down, then jump through the Weapon Armory door."
                    return 'laser_weapon_armory'
            
                else:
                    print "DOES NOT COMPUTE!"
                    return 'central_corridor'
            
            def laser_weapon_armory():
                print "You do a dive roll into the Weapon Armory, crouch and scan the room"
                print "for more Gothons that might be hiding.  It's dead quiet, too quiet."
                print "You stand up and run to the far side of the room and find the"
                print "neutron bomb in its container.  There's a keypad lock on the box"
                print "and you need the code to get the bomb out.  If you get the code"
                print "wrong 10 times then the lock closes forever and you can't"
                print "get the bomb.  The code is 3 digits."
                code = "%d%d%d" % (randint(1,9), randint(1,9), randint(1,9))
                guess = raw_input("[keypad]> ")
                guesses = 0
            
                while guess != code and guesses < 10:
                    print "BZZZZEDDD!"
                    guesses += 1
                    guess = raw_input("[keypad]> ")
            
                if guess == code:
                    print "The container clicks open and the seal breaks, letting gas out."
                    print "You grab the neutron bomb and run as fast as you can to the"
                    print "bridge where you must place it in the right spot."
                    return 'the_bridge'
                else:
                    print "The lock buzzes one last time and then you hear a sickening"
                    print "melting sound as the mechanism is fused together."
                    print "You decide to sit there, and finally the Gothons blow up the"
                    print "ship from their ship and you die."
                    return 'death'
            
            
            def the_bridge():
                print "You burst onto the Bridge with the neutron destruct bomb"
                print "under your arm and surprise 5 Gothons who are trying to"
                print "take control of the ship.  Each of them has an even uglier"
                print "clown costume than the last.  They haven't pulled their"
                print "weapons out yet, as they see the active bomb under your"
                print "arm and don't want to set it off."
                
                action = raw_input("> ")
            
                if action == "throw the bomb":
                    print "In a panic you throw the bomb at the group of Gothons"
                    print "and make a leap for the door.  Right as you drop it a"
                    print "Gothon shoots you right in the back killing you."
                    print "As you die you see another Gothon frantically try to disarm"
                    print "the bomb. You die knowing they will probably blow up when"
                    print "it goes off."
                    return 'death'
            
                elif action == "slowly place the bomb":
                    print "You point your blaster at the bomb under your arm"
                    print "and the Gothons put their hands up and start to sweat."
                    print "You inch backward to the door, open it, and then carefully"
                    print "place the bomb on the floor, pointing your blaster at it."
                    print "You then jump back through the door, punch the close button"
                    print "and blast the lock so the Gothons can't get out."
                    print "Now that the bomb is placed you run to the escape pod to"
                    print "get off this tin can."
                    return 'escape_pod'
                else:
                    print "DOES NOT COMPUTE!"
                    return "the_bridge"
            
            def escape_pod():
                print "You rush through the ship desperately trying to make it to"
                print "the escape pod before the whole ship explodes.  It seems like"
                print "hardly any Gothons are on the ship, so your run is clear of"
                print "interference.  You get to the chamber with the escape pods, and"
                print "now need to pick one to take.  Some of them could be damaged"
                print "but you don't have time to look.  There's 5 pods, which one"
                print "do you take?"
            
                good_pod = randint(1,5)
                guess = raw_input("[pod #]> ")
            
            
                if int(guess) != good_pod:
                    print "You jump into pod %s and hit the eject button." % guess
                    print "The pod escapes out into the void of space, then"
                    print "implodes as the hull ruptures, crushing your body"
                    print "into jam jelly."
                    return 'death'
                else:
                    print "You jump into pod %s and hit the eject button." % guess
                    print "The pod easily slides out into space heading to"
                    print "the planet below.  As it flies to the planet, you look"
                    print "back and see your ship implode then explode like a"
                    print "bright star, taking out the Gothon ship at the same"
                    print "time.  You won!"
                    exit(0)
            
            
            ROOMS = {
                'death': death,
                'central_corridor': central_corridor,
                'laser_weapon_armory': laser_weapon_armory,
                'the_bridge': the_bridge,
                'escape_pod': escape_pod
            }
            
            
            def runner(map, start):
                next = start
            
                while True:
                    room = map[next]
                    print "\n--------"
                    next = room()
            
            runner(ROOMS, 'central_corridor')
            

            代碼不少,不過還是從頭寫完吧。確認它能運行,然后玩一下看看。

            你應該看到的結果?

            我玩起來時這樣的:

            $ python ex41.py 
            
            --------
            The Gothons of Planet Percal #25 have invaded your ship and destroyed
            your entire crew.  You are the last surviving member and your last
            mission is to get the neutron destruct bomb from the Weapons Armory,
            put it in the bridge, and blow the ship up after getting into an 
            escape pod.
            
            
            You're running down the central corridor to the Weapons Armory when
            a Gothon jumps out, red scaly skin, dark grimy teeth, and evil clown costume
            flowing around his hate filled body.  He's blocking the door to the
            Armory and about to pull a weapon to blast you.
            > dodge!
            Like a world class boxer you dodge, weave, slip and slide right
            as the Gothon's blaster cranks a laser past your head.
            In the middle of your artful dodge your foot slips and you
            bang your head on the metal wall and pass out.
            You wake up shortly after only to die as the Gothon stomps on
            your head and eats you.
            
            --------
            Such a luser.
            learnpythehardway $ python ex/ex41.py 
            
            --------
            The Gothons of Planet Percal #25 have invaded your ship and destroyed
            your entire crew.  You are the last surviving member and your last
            mission is to get the neutron destruct bomb from the Weapons Armory,
            put it in the bridge, and blow the ship up after getting into an 
            escape pod.
            
            
            You're running down the central corridor to the Weapons Armory when
            a Gothon jumps out, red scaly skin, dark grimy teeth, and evil clown costume
            flowing around his hate filled body.  He's blocking the door to the
            Armory and about to pull a weapon to blast you.
            > tell a joke
            Lucky for you they made you learn Gothon insults in the academy.
            You tell the one Gothon joke you know:
            Lbhe zbgure vf fb sng, jura fur fvgf nebhaq gur ubhfr, fur fvgf nebhaq gur ubhfr.
            The Gothon stops, tries not to laugh, then busts out laughing and can't move.
            While he's laughing you run up and shoot him square in the head
            putting him down, then jump through the Weapon Armory door.
            
            --------
            You do a dive roll into the Weapon Armory, crouch and scan the room
            for more Gothons that might be hiding.  It's dead quiet, too quiet.
            You stand up and run to the far side of the room and find the
            neutron bomb in its container.  There's a keypad lock on the box
            and you need the code to get the bomb out.  If you get the code
            wrong 10 times then the lock closes forever and you can't
            get the bomb.  The code is 3 digits.
            [keypad]> 123 
            BZZZZEDDD!
            [keypad]> 234
            BZZZZEDDD!
            [keypad]> 345
            BZZZZEDDD!
            [keypad]> 456
            BZZZZEDDD!
            [keypad]> 567
            BZZZZEDDD!
            [keypad]> 678
            BZZZZEDDD!
            [keypad]> 789
            BZZZZEDDD!
            [keypad]> 384
            BZZZZEDDD!
            [keypad]> 764
            BZZZZEDDD!
            [keypad]> 354
            BZZZZEDDD!
            [keypad]> 263
            The lock buzzes one last time and then you hear a sickening
            melting sound as the mechanism is fused together.
            You decide to sit there, and finally the Gothons blow up the
            ship from their ship and you die.
            
            --------
            You died.  You kinda suck at this.
            

            加分習題?

            1. 解釋一下返回至下一個房間的工作原理。
            2. 創建更多的房間,讓游戲規模變大。
            3. 除了讓每個函數打印自己以外,再學習一下“文檔字符串(doc strings)”式的注解。看看你能不能將房間描述寫成文檔注解,然后修改運行它的代碼,讓它把文檔注解打印出來。
            4. 一旦你用了文檔注解作為房間描述,你還需要讓這個函數打印出用戶提示嗎?試著讓運行函數的代碼打出用戶提示來,然后將用戶輸入傳遞到各個函數。你的函數應該只是一些 if 語句組合,將結果打印出來,并且返回下一個房間。
            5. 這其實是一個小版本的“有限狀態機(finite state machine)”,找資料閱讀了解一下,雖然你可能看不懂,但還是找來看看吧。
            6. 我的代碼里有一個 bug,為什么門鎖要猜測 11 次?

            Project Versions

            Table Of Contents

            Previous topic

            習題 40: 字典, 可愛的字典

            Next topic

            習題 42: 物以類聚

            This Page

            <span id="7ztzv"></span>
            <sub id="7ztzv"></sub>

            <span id="7ztzv"></span><form id="7ztzv"></form>

            <span id="7ztzv"></span>

                  <address id="7ztzv"></address>

                      亚洲欧美在线