<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                # 練習43.基本的面向對象的分析和設計 在這節練習,我想給你介紹一個使用python創建某類東西的過程,也就是“面向對象編程”(OOP)。我把它叫做一個過程,是因為我將給出一系列按順序進行的步驟,但是你也不應該死板的遵循這個步驟,企圖用它解決所有難題。它們對于許多編程問題只是一個良好的開頭,而不應該被認為是解決這些問題的唯一方法。這個過程只是一個你可以遵循的方法: > 1. 寫出或畫出你的問題 > 1. 從1中提煉關鍵問題并搜索相關資料 > 1. 為2中的問題創建一個有層次結構的類和對象映射 > 1. 編寫類和測試代碼,并保證他們運行 > 1. 重復并精煉 按照這個順序執行流程,叫做“自頂向下”的方式,意思是說,它從非常抽象寬松的想法開始,然后慢慢提煉,直到想法是堅實的東西,然后你再開始編碼。 首先我只是寫出這個問題,并試圖想出任何我想要的東西就可以了。也許我會畫一兩個圖表,或者某種可能的地圖,甚至給自己寫了一系列的電子郵件描述這個問題。這給了我表達了問題的關鍵概念的方法,并探測出我對于這個游戲有什么具體的想法和了解。 接下來,我瀏覽這些筆記,圖表以及描述,通過這些記錄我找到我需要的關鍵問題點。有一個簡單的技巧:簡單地列出你的筆記和圖表中所有的名詞和動詞,然后寫出他們是如何相關的。這一步其實也我為我下一步要寫的類、對象、以及函數等提供了命名列表。我利用這個概念列表,研究任何我不明白的地方,如果我需要,我還可以進一步完善它們。 一旦我完成這個列表,我可以創建的一個簡單的輪廓/樹用來說明這些概念之間的關系。你還可以對著你的名詞列表并詢問“這個名詞和其他的是一個概念嗎?或者它們有一個通用的父類嗎,那它們的父類是什么?”持續檢查,直到你得到一個有層次結構的類,它應該像一棵簡單的樹或者圖表。然后檢查你的動詞列表,看它們是否可以作為函數的名字添加到你的類樹種。 隨著這棵類樹的生成,我坐下來寫一些基本的框架代碼,代碼中只包括剛才提到的類,類中包含的函數。然后我再寫一個測試用例,用來檢驗我剛才寫的類是正確的。有時候我可能只需要在開始寫一段測試代碼,但是更多的時候,我需要寫一段測試,再寫一段代碼,再寫一段測試...直到整個項目完成。 最后,在我完成更多的工作之前,我周期性的重復和精煉這個流程,是他變得清楚和易于理解。如果我在一個沒有預料到的地方被一些概念或問題卡住,我會停下來在這一小部分上投入更大的精力來分析解決,直到我解決了這問題,再繼續下去。 這節練習中,我將通過建造一個游戲引擎帶大家學習這一流程。 ## 分析一個簡單的游戲引擎 我打算制作一個叫做 "Gothons from Planet Percal #25"的游戲,這個一個小型的太空冒險游戲。 ## 寫或畫出這個問題 我為這個游戲寫了一小段描述: “外星人乘坐一個宇宙飛船入侵,我們的英雄需要通過一個迷宮似的房間擊敗他們,然后他才能逃入一個逃生艙到達下面的行星。游戲將更像一個有著文本輸出和有趣的死法的Zork或冒險類型游戲。游戲將包括一個引擎運行充滿房間或場景的地圖。 當玩家進入房間,每個房間將打印自己的描述,然后告訴引擎運行下一個地圖。” 我先描述每個場景: Death: 這是玩家死亡的場景,應該是有趣的。 Central Corridor: 這是游戲的起點,在這里已經有一個外星人等待英雄的到來,它們需要被一個玩笑打敗。 Laser Weapon Armory: 這是英雄得到了中子彈獲得的逃生艙之前要炸毀的船。它有一個需要英雄猜數的鍵盤。 The Bridge: 和外星人戰斗的另一個場景,英雄防止炸彈的地方。 Escape Pod: 英雄逃脫的場景,但是需要英雄找對正確的逃生艙 現在,我可以繪制出它們的地圖,或者對每個房間再多寫一些描述,或者其他一些我腦中出現的想法。 ## 提取關鍵概念并研究他們 現在我已經有足夠多的信息還提取出名詞,并分析它們的類結構。首先我列出所有的名詞: > - Alien > - Player > - Ship > - Maze > - Room > - Scene > - Gothon > - Escape Pod > - Planet > - Map > - Engine > - Death > - Central Corridor > - Laser Weapon Armory > - The Bridge 我也可能要列出所有的動詞,看它們能否作為函數的名字,不過現在我要先跳過這一步。 你需要研究所有你現在還不知道的概念。例如,我可能會玩幾個這種類型的游戲,并確保知道他們是如何工作的。我可能會研究船舶和炸彈的設計和工作原理。也許我會研究怎么樣將游戲中的數據或狀態存儲在數據庫等一些技術上的問題。我做完這個研究之后,我可能會回到第1步重新開始,根據新的信息,重寫描述和提取新的概念。 ## 創建一個層次結構的類和對象映射的概念 當我完成上面的步驟,我通過思考“哪些是類似于其他東西的”,把名詞列表轉換成一個有層次結構的類樹,同樣,我也會思考,哪些單詞是其他東西的基礎呢? 馬上我發現,"Room" 和 "Scene"對于我要做的事情來說基本上是一樣的事情。在這個游戲中,我選擇使用"Scene" 。接下來我發現,所有的特殊房間比如"Central Corridor"基本上也跟"Scene"是一樣的。我發現"Death"也是一個"Scene", 由于我選擇了"Scene"而不是"Room",你可以有一個“死亡場景”,而是不一個很奇怪的“死亡房間”。"Maze"和"Map"基本一樣,所以我選擇使用"Map",因為我更多的時候都用它。我不想做一個戰斗系統,所以我會先忽略"Alien"和 "Player",但是會把他們保存下來以供以后使用。"Planet"也可能僅僅是另一個場景,而不是什么具體的事情。 在此之后,我開始創建一個層次結構的類: > - Map > - Engine > - Scene > - Death > - Central Corridor > - Laser Weapon Armory > - The Bridge > - Escape Pod 然后,我會找出說明中每個動詞都需要什么行動。比如,我從說明中得知,我需要一個方法來"run"這個引擎,通過地圖獲得下一個場景"get the next scene",獲得"opening scene",或者"enter"一個場景。我把這些加到類樹里: > - Map- next_scene- opening_scene > - Engine- play > - Scene- enter* Death* Central Corridor* Laser Weapon Armory* The Bridge* Escape Pod 注意一下,我只是把`-enter`放到`Scene`下面,因為我知道所有的場景都會繼承它并重寫它。 ## 編碼類和測試代碼并運行它們 當我有了這個類樹和一些功能之后,我在編輯器中打開源文件,并嘗試編寫代碼。通常,我會復制粘貼這棵類樹到源文件中,然后編輯它。下面是一個如何編碼的小例子,文件末尾包含一個簡單的測試用例: ~~~ class Scene(object): def enter(self): pass class Engine(object): def __init__(self, scene_map): pass def play(self): pass class Death(Scene): def enter(self): pass class CentralCorridor(Scene): def enter(self): pass class LaserWeaponArmory(Scene): def enter(self): pass class TheBridge(Scene): def enter(self): pass class EscapePod(Scene): def enter(self): pass class Map(object): def __init__(self, start_scene): pass def next_scene(self, scene_name): pass def opening_scene(self): pass a_map = Map('central_corridor') a_game = Engine(a_map) a_game.play() ~~~ 在這個文件中,你可以看到我只是復制了我想要的層次結構,然后一點點的補齊代碼再運行它,看看它在這個基本結構中是否運行順利。 在這節練習后面的部分,你會填補這段代碼的其余部分,使其正常工作,以配合練習開頭的游戲描述。 ## 重復并精煉 在我提供的流程中,最后一步并不是實際意義上的一步,而是要做一個循環。在編程的世界里,你永遠做不到一次通過,相反,你退回整個過程,并再次根據你從后面的步驟中了解到的信息完善它。有時候我已經到了第3步,但是我發現我還需要在第1、2步做更多工作,我會停下來并返回去完善它。有時候我也會突然靈光一閃,跳到最后,用我腦子里更好的解決方案編碼實現,但是之后,我仍然會回去完成前面的步驟,以確保我的工作覆蓋了所有的可能性。 在這一過程的另一個觀點是,你不是僅在一個層面上使用這個流程,當你遇到某些特定問題的時候,你可以在任意一個層級上使用該流程。比方說,我不知道如何寫`Engine.play`方法,我可以靜下心來用這個流程只做這一種功能,直到弄清楚這個方法怎么寫。 ## 自頂向下和自下而上 因為這個流程在最抽象的概念(頂部)開始,然后再下降到實際執行過程中,因此這一流程通常標示為“自上而下”。我希望你使用這一流程,但你也應該知道,還有另一種方式來解決程序中的問題,這種方式是從代碼開始,再“上升”到抽象的概念問題。這種方式被稱為“自下而上”。下面是自下而下方式所遵循的步驟: > 1. 取一小塊問題,編寫一些代碼,并讓他勉強運行 > 1. 完善代碼,將其轉換成一些更正式的包含類和自動化測試的代碼。 > 1. 提取其中的關鍵概念,并嘗試找出研究他們。 > 1. 寫出到底發生了什么的描述。 > 1. 繼續完善代碼,也可能是把它扔掉,并重新開始。 > 1. 移動到其他問題上,重復步驟。 當你需要更優質的代碼,并在代碼中更自然的思考你要解決的問題時,這種方式更好一些。尤其是當你知道小塊的難題,但沒有足夠的信息把握整個概念的時候,這個方式是一個解決問題很好的辦法。將問題分解成碎片并探索代碼,直到你解決這個問題。然而,你解決問題的途徑可能是緩慢而曲折的,所以,我的這一流程中也包含后退并反復研究問題,直到你通過自己所為解決所有難題。 ## “來自 Percal 25 號行星的哥頓人”的代碼 我要告訴你我解決上述問題的最終辦法,但我不希望你只是直接跳到這里并輸入代碼。我希望你能通過我的描述,完成我寫的那個簡單粗糙的代碼框架,并讓他運行起來。當你有了自己的解決方案時,你可以回來看看我是怎么解決的。 我準備把文件`ex43.py`拆成小塊,再一一解釋,而不是一次性提供完整的代碼。 ~~~ from sys import exit from random import randint ~~~ 這只是我們游戲需要導入的包,沒什么新奇的。 ~~~ class Scene(object): def enter(self): print "This scene is not yet configured. Subclass it and implement enter()." exit(1) ~~~ 正如你在框架代碼里看到的,我創建了基礎類`Scene`,它將包含所有scene要做的所有的事。在這段代碼中,它們并沒有做什么,所以這只是給你的一個如果創建基類的示范。 ~~~ class Engine(object): def __init__(self, scene_map): self.scene_map = scene_map def play(self): current_scene = self.scene_map.opening_scene() last_scene = self.scene_map.next_scene('finished') while current_scene != last_scene: next_scene_name = current_scene.enter() current_scene = self.scene_map.next_scene(next_scene_name) # be sure to print out the last scene current_scene.enter() ~~~ 我同樣創建了類`Engine`,并且你能看到我已經使用了方法`Map.opening_scene` 和 `Map.next_scene`。因為在我寫`Map`類之前,做了一點計劃,我可以假設我后面會寫這些,然后提前使用它們。 ~~~ class Death(Scene): quips = [ "You died. You kinda suck at this.", "Your mom would be proud...if she were smarter.", "Such a luser.", "I have a small puppy that's better at this." ] def enter(self): print Death.quips[randint(0, len(self.quips)-1)] exit(1) ~~~ 我的第一個場景是一個叫做`Death`的場景,它給你展現了你能寫的最簡單的場景。 ~~~ class CentralCorridor(Scene): def enter(self): 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' ~~~ 接下來,我創建了`CentralCorridor`,這是游戲的開始。我在寫`Map`之前,為游戲制作了這個場景,是因為我后面要引用它們。 ~~~ class LaserWeaponArmory(Scene): def enter(self): 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' class TheBridge(Scene): def enter(self): print "You burst onto the Bridge with the netron 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" class EscapePod(Scene): def enter(self): 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!" return 'finished' class Finished(Scene): def enter(self): print "You won! Good job." return 'finished' ~~~ 這是游戲剩下的場景。因為我知道我需要他們,并且已經想好他們應該如何交織在一起,所以我可以直接編碼。 順便說一下,我不是直接輸入這些代碼。記得我說過的嗎,用增量的方法嘗試構建所有的代碼,一次只寫一小部分。我只是給你看了最終的結果。 ~~~ class Map(object): scenes = { 'central_corridor': CentralCorridor(), 'laser_weapon_armory': LaserWeaponArmory(), 'the_bridge': TheBridge(), 'escape_pod': EscapePod(), 'death': Death(), 'finished': Finished(), } def __init__(self, start_scene): self.start_scene = start_scene def next_scene(self, scene_name): val = Map.scenes.get(scene_name) return val def opening_scene(self): return self.next_scene(self.start_scene) ~~~ 在這之后,我寫了`Map`類,你可以看到它通過名字把所有的場景存在了字典中。我把這個字典叫做`Map.scenes`。這也是為什么map是在scens之后才寫的原因,因為這個字典需要包含所有已存在的場景。 ~~~ a_map = Map('central_corridor') a_game = Engine(a_map) a_game.play() ~~~ 最后,我讓我的代碼通過創建一個`Map`,并在調用`play`之前把map交給`Engine`,把游戲運行起來, ## 你看到的結果 確保你明白這個游戲,并且首先嘗試自己解決它。如果你被難住了,可以閱讀一小部分我的代碼,然后再嘗試自己搞定它。 當我運行我的游戲的時候,我可以看到: ~~~ $ python ex43.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. Your mom would be proud...if she were smarter. ~~~ ## 附加題 > 1. 修改這個游戲!你可能不喜歡這個游戲。讓游戲運行起來,然后按照你的喜好修改它。這是你的電腦,你可以用它做你想做的事情 > 1. 代碼中有一個bug,為什么門鎖了11次? > 1. 解釋一下返回至下一個房間的工作原理。 > 1. 增加作弊代碼,這樣你能通過一些更難的房間。我能只在一行上加兩個單詞做到這些。 > 1. 回到我的描述和分析,嘗試為英雄和他遇見的各種哥頓人創建一個小型作戰系統。 > 1. 這其實是一個小版本的“有限狀態機(finite state machine)”,找資料閱讀了解一下,雖然你可能看不懂,但還是找來看看吧。 ## 常見問題 ### Q: 我在哪里可以為我的游戲找到故事情節 > 你可以就像給朋友講述一個故事一樣,來創建游戲。或者你可以采取簡單的你喜歡的書或電影場景。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看