笨方法”学Python3,习题 43:基本的面向对象分析和设计

1、大致理解设计游戏的思维方式

一、面向对象编程(OOP)方式构建的基本流程

这个流程是“自顶向下”(top down)的,从抽象的概念逐步细化到具体的代码

1、把要解决的问题写下来,或者画出来(问题描述、结构关系图等)

2、将第一条中的关键概念提取出来并加以研究(问题名词、动词提取到代码命名中)

3、创建一个类层次结构和对象图(结构关系图、父类子类、函数方法的关系)

4、用代码实现各个类,并写一个测试来运行它们(骨架代码逐步细化)

5、重复上述步骤并细化代码


二、简单游戏引擎的分析

游戏名:《来自 Percal 25 号行星的哥顿人》

1、把问题写下来或者画出来

游戏描述:“外星人入侵了宇宙飞船,我们的英雄需要通过各种房间组成的迷宫,打败遇到的外星人,这样才能通过救生船回到下面的行星上去。这个游戏会用文字输出各种搞笑的死法,会用到一个引擎来带动一张充满房间和场景的地图,玩家进入房间时会显示出对房间的描述并告诉引擎下一步一个到哪个房间去。”

场景描述:

  • 死亡(death):玩家死去的场景,搞笑
  • 中央走廊(central corridor):游戏的起点,有哥顿人把守,要讲一个笑话才能继续
  • 激光武器库(laser weapon armory):有一个中子弹,在乘坐救生船离开时要用它炸飞船,房间有一个数字键盘,需要猜测密码组合
  • 飞船主控舱(the bridge):另一个战斗场景,需要在这里埋炸弹
  • 救生舱(escape pod):逃离的场景,但需要猜对是哪艘救生船

2、提取和研究关键概念

提取名词列表:

  • 外星人(Alien)
  • 迷宫(Maze)
  • 玩家(Player)
  • 房间(Room)
  • 飞船(Ship)
  • 场景(Scene)
  • 哥顿人(Gothon)
  • 死亡(Death)
  • 救生船(Escape Pod)
  • 中央走廊(Central Corridor)
  • 行星(Planet)
  • 激光武器库(Laser Weapon Armory)
  • 地图(Map)
  • 主控舱(The Bridge)
  • 引擎(Engine)

3、为各种概念创建类层次结构和对象图

可以发现“场景”和“房间”基本上是一个东西,所以可以使用“场景”来代替“房间”,而“死亡”适合“死亡场景”,就将其归为“场景”,“迷宫”和“地图”大致一样,就用“地图”

创建类层次结构:

  • Map
  • Engine
  • Scene
  • Death
  • Central Corridor
  • Laser Weapon Armory
  • The Bridge
  • Escape Pod

添加动词结构:

  • Map
  • -next_scene
  • -opening_scene
  • Engine
  • -play
  • Scene
  • -enter
  • Death
  • Central Corridor
  • Laser Weapon Armory
  • The Bridge
  • Escape Pod

4、编写类和运行类的测试代码

根据类结构编写测试代码:

所写的代码:
class Scene(object):def enter(self):passclass Engine(object):def __init__(self, scene_map):passdef play(self):passclass Death(Scene):def enter(self):passclass CentralCorridor(Scene):def enter(self):passclass LaserWeaponArmory(Scene):def enter(self):passclass TheBridge(Scene):def enter(self):pass   class EscapePod(Scene):def enter(self):passclass Map(object):def __init__(self, start_scene):passdef next_scene(self, scene_name):passdef opening_scene(self):passa_map = Map('central_corridor')
a_game = Engine(a_map)
a_game.play()

5、重复和细化

重复整个流程,逐步细化内容


三、自顶向下与自底向上

自底向上的一般步骤:

1、取出要解决的问题中的一小块,写些代码让它差不多能运行

2、加上类和自动测试,细化代码让它更为正式

3、把关键概念抽取出来然后研究它们

4、把真正需要实现的东西描述出来

5、回去细化代码,有可能需要全部丢弃重头做起

6、在问题的另外一小块里重复上述流程


四、《来自 Percal 25 号行星的哥顿人》的代码

1、导入部分:

from sys import exit
from random import randint
from textwrap import dedent 

① textwrap 模块的 dedent 函数

取出字符串开头的空白,方便写三引号字符串

2、创建 Scene 基类

class Scene(object):def enter(self):print('This scene is not yet configured.')print('Subclass it and implement enter().')exit(1)

Scene 基类包含所有场景的通用信息

3、创建 Engine 类

class Engine(object):def __init__(self, scene_map):self.scene_map = scene_mapdef 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 scenecurrent_scene.enter()

这里用了Map.opening_scene 和 Map.next_scene 方法,是假设这些方法已经写好了的,这里是拿来使用的

4、创建 Death 场景

class Death(Scene):quips = ["You died. You kinda suck at this","You mom would be proud...if she were smarter.","Such a luser.","I have a small puppy that's better at this.","You're worse than your Dad's jokes."]def enter(self):print(Death.quips[randint(0, len(self.quips)-1)]) exit(1)

5、创建 CentralCorridor 场景

class CentralCorridor(Scene):def enter(self):print(dedent("""The Gothons of planet Percal #25 haveinvaded your ship and desteoyed 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 afther getiing 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 filled body.He's blocking the door to the Armory and about topull a weapon blast you."""))action = input('> ')if action == "shoot!":print(dedent("""Quick on the draw you yank out your blaster and fire it at the Gothon. His clown costume is flowing and moving around his body, which throws off you aim.This completely ruins his brand new costume but misses him entirely,which makes him fly into an insane rage and blast you repeatedly in the face untill you are dead.Then he eats you."""))return 'death'elif action == 'dodge!':print(dedent("""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."""))return 'death'elif action == 'tell a joke':print(dedent("""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, jura 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."""))return 'laser_weapon_armory'else:print('DOES NOT COMPUTE! ')return 'central_corridor'

CentralCorridor 场景是游戏的初始位置,这里运用到了 dedent 函数,可以观察其作用

6、创建其他场景

class LaserWeaponArmory(Scene):def enter(self):print(dedent("""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."""))code = f"{randint(1,9)}{randint(1,9)}{randint(1,9)}"guess = input("[keypad]> ")guesses = 0while guess != code and guesses < 10:print('BZZZZEDDD!')guesses += 1guess = input("[keypad]> ")if guess == code:print(dedent("""The container clicks open and the seal breaks, letting gas out. You grab the neutron bomb and run as fast as you can to he bridge where you must place it in the right spot."""))return 'the_bridge'else:print(dedent("""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 you die."""))return 'death'class TheBridge(Scene):def enter(self):print(dedent("""You burst onto the Bridge with the netron destruct bomb under your arm and surprise 5 Gothons who are trying to take control of the ship.Each of them has an even uglier clown costume than the last. They haven't pulled their weapons out yet, as they see the active bomb under your arm and don't want to set it off."""))action = input('> ')if action == 'throw the bomb': print(dedent("""In a panic you throw the bomb at the group of Gothons and make a leap for the door. Right as you drop it a Gothon shoots you right in the back killing you. As you die you see another Gothon frantically try to disarm the bomb. You die knowing they will probably blow up when it goes off."""))return 'death'elif action == 'slowly place the bomb':print(dedent("""You point your blaster at the bomb under your arm and the Gothons put their hands up and start to sweat .You inch backward to the door, open it ,and then carefully place the bomb on the floor, pointing your blaster at it. You then jump back through the door, punch the close button and blast the lock so the Gothon can't get out . Now that the bomb is placed you run to the escape pod to get off this tin can."""))return 'escape_pod' else:print('DOES NOT COMPUTE!')return 'the_bridge'class EscapePod(Scene):def enter(self):print(dedtne("""You rush through the ship desperately trying to make it to the escape pod before the whole ship explodes. It seems like hardly any Gothons are on the ship, so your run is clear of interference. You get to the chamber with the escape pods ,and now need to pick one to take. Some of them could be damage but you don't have time to look.There's 5 pods, which one do you take?"""))good_pod = randint(1,5)guess = input('[pod #]> ')if int(guess) != good_pod:print(dedent("""You jump into pod {guess} and hit the eject button.The escapes pod  out into the void of space, then implodes as the hull ruptures, crushing your body into jam jelly."""))return 'death'   else:print(dedent("""You jump into pod {guess} and hit the eject button.The pod easily slides out into space heading to the planet below. As it flies to the planet, you look back and see your ship implode then explode like abright star, taking out the Gothon ship at the same time.You won!"""))return 'finished'class Finished(Scene):def enter(self):print("You won! Good job.")return 'finished'

创建 Map 基类

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_scenedef next_scene(self, scene_name):val = Map.scenes.get(scene_name)return valdef opening_scene(self):return self.next_scene(self.start_scene)

运行代码

a_map = Map('central_corridor')
a_game = Engine(a_map)
a_game.play()


五、整段脚本及运行结果

所写的代码:
from sys import exit
from random import randint
from textwrap import dedent   class Scene(object):def enter(self):print('This scene is not yet configured.')print('Subclass it and implement enter().')exit(1)class Engine(object):def __init__(self, scene_map):self.scene_map = scene_mapdef 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 scenecurrent_scene.enter()class Death(Scene):quips = ["You died. You kinda suck at this.","You mom would be proud...if she were smarter.","Such a luser.","I have a small puppy that's better at this.","You're worse than your Dad's jokes.",]def enter(self):print(Death.quips[randint(0, len(self.quips)-1)]) exit(1)class CentralCorridor(Scene):def enter(self):print(dedent("""The Gothons of planet Percal #25 haveinvaded your ship and desteoyed 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 afther getiing 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 filled body.He's blocking the door to the Armory and about topull a weapon blast you."""))action = input('> ')if action == "shoot!":print(dedent("""Quick on the draw you yank out your blaster and fire it at the Gothon. His clown costume is flowing and moving around his body, which throws off you aim.This completely ruins his brand new costume but misses him entirely,which makes him fly into an insane rage and blast you repeatedly in the face untill you are dead.Then he eats you."""))return 'death'elif action == 'dodge!':print(dedent("""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."""))return 'death'elif action == 'tell a joke':print(dedent("""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, jura 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."""))return 'laser_weapon_armory' else:print('DOES NOT COMPUTE!')return 'central_corridor'class LaserWeaponArmory(Scene):def enter(self):print(dedent("""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."""))code = f"{randint(1,9)}{randint(1,9)}{randint(1,9)}"guess = input("[keypad]> ")guesses = 0while guess != code and guesses < 10:print('BZZZZEDDD!')guesses += 1guess = input("[keypad]> ")if guess == code:print(dedent("""The container clicks open and the seal breaks, letting gas out. You grab the neutron bomb and run as fast as you can to he bridge where you must place it in the right spot."""))return 'the_bridge'else:print(dedent("""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 you die."""))return 'death'class TheBridge(Scene):def enter(self):print(dedent("""You burst onto the Bridge with the netron destruct bomb under your arm and surprise 5 Gothons who are trying to take control of the ship.Each of them has an even uglier clown costume than the last. They haven't pulled their weapons out yet, as they see the active bomb under your arm and don't want to set it off."""))action = input('> ')if action == 'throw the bomb':print(dedent("""In a panic you throw the bomb at the group of Gothons and make a leap for the door. Right as you drop it a Gothon shoots you right in the back killing you. As you die you see another Gothon frantically try to disarm the bomb. You die knowing they will probably blow up when it goes off."""))return 'death'elif action == 'slowly place the bomb':print(dedent("""You point your blaster at the bomb under your arm and the Gothons put their hands up and start to sweat .You inch backward to the door, open it ,and then carefully place the bomb on the floor, pointing your blaster at it. You then jump back through the door, punch the close button and blast the lock so the Gothon can't get out . Now that the bomb is placed you run to the escape pod to get off this tin can."""))return 'escape_pod'else:print('DOES NOT COMPUTE!')return 'the_bridge'class EscapePod(Scene):def enter(self):print(dedtne("""You rush through the ship desperately trying to make it to the escape pod before the whole ship explodes. It seems like hardly any Gothons are on the ship, so your run is clear of interference. You get to the chamber with the escape pods ,and now need to pick one to take. Some of them could be damage but you don't have time to look.There's 5 pods, which one do you take?"""))good_pod = randint(1,5)guess = input('[pod #]> ')if int(guess) != good_pod:print(dedent("""You jump into pod {guess} and hit the eject button.The escapes pod  out into the void of space, then implodes as the hull ruptures, crushing your body into jam jelly."""))return 'death'   else:print(dedent("""You jump into pod {guess} and hit the eject button.The pod easily slides out into space heading to the planet below. As it flies to the planet, you look back and see your ship implode then explode like abright star, taking out the Gothon ship at the same 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_scenedef next_scene(self, scene_name):val = Map.scenes.get(scene_name)return valdef opening_scene(self):return self.next_scene(self.start_scene)a_map = Map('central_corridor')
a_game = Engine(a_map)
a_game.play()
---------------------------------------------------------------------------------------------------
应该看到的结果:
PS D:代码> & D:/软件/python/python.exe d:/代码/test.pyThe Gothons of planet Percal #25 haveinvaded your ship and desteoyed 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 afther getiing 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 filled body.
He's blocking the door to the Armory and about topull a weapon blast you.> tell a jokeLucky 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, jura 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]> 153
BZZZZEDDD!
[keypad]> 123
BZZZZEDDD!
[keypad]> 999
BZZZZEDDD!
[keypad]> 122
BZZZZEDDD!
[keypad]> 111
BZZZZEDDD!
[keypad]> 000
BZZZZEDDD!
[keypad]> 999
BZZZZEDDD!
[keypad]> 777
BZZZZEDDD!
[keypad]> 888
BZZZZEDDD!
[keypad]> 555
BZZZZEDDD!
[keypad]> 444The 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 you die.You mom would be proud...if she were smarter.


总结:

1、设计游戏脚本要从抽象的概念开始,逐步细化到具体的代码

2、要游戏中的场景动作分别与脚本中的类方法匹配,弄清楚中间的关系

3、重复编写,逐步细化

^ v ^,知乎此系列文章内容均会在微信公众号中同步更新,公众号:小民有个小旮旯

笨方法python3_“笨方法”学Python3,习题 43 。相关推荐

  1. 笨方法python3_“笨方法”学Python3,习题 41 。

    笨方法"学Python3,习题 41:学习面向对象术语 1.有哪些术语 ? 2.术语的意思是什么 ? 一.专有词汇练习 类(class):告诉 Python 创建新类型的东西 对象(obje ...

  2. 笨方法python3_“笨方法”学Python3,习题 34 。

    笨方法"学Python3,习题 34:访问列表的元素 1.如何访问列表的元素 ? 2.什么是索引 ? 3.序数与基数的区别是什么 ? 一.练习 访问列表前,我们需要知道什么是序数.基数和索引 ...

  3. 笨办法学python3.6 pdf_“笨办法”学Python3.pdf

    作 者 :(美)泽德 A.肖(Zed A. Shaw)著 出版发行 : 北京:人民邮电出版社 , 2018.06 ISBN号 :978-7-115-47881-8 页 数 : 255 原书定价 : 3 ...

  4. excel切片器_Excel表格中筛选数据,你的方法太笨了

    在Excel表格中筛选数据,一般是这样的: @所有人,本周有一个重要知识点,马上点击学习↓ 不要再用数据透视表了!再忙都要看 打开筛选按钮,然后去掉全选,然后从下拉中勾选要筛选的内容 如果要筛选很多项 ...

  5. 笨办法学python3 学习笔记 习题43 基本的面向对象分析和设计

    习题43 基本的面向对象分析和设计 通过面向对象编程(OOP)构建一些东西的流程(常用)(自顶向下) 把要解决的问题写下来,或者画出来. 将第一条中的关键概念提取出来并加以研究. 创建一个类层次结构和 ...

  6. 笨办法学python3-笨方法学Python3(21-44)

    接着前天的总结 习题21:函数可以返回某些东西 定义函数的加减乘除,以及嵌套使用 习题22:回顾以前学的知识 习题23:字符串.字节串和字符编码 综合运用字符串.函数.文件读取等知识.详情如下: fr ...

  7. 一木.溪桥学Python-11:迭代器、生成器、面象对象class MyClass:、self 参数、 __init__() 方法、__str__() 方法

    一木.溪桥 在Logic Education跟Amy学Python 逻辑教育 :https://logicedu.ke.qq.com 12期:Python基础课 一木.溪桥学Python-11:迭代器 ...

  8. 华为手机设置页面黑色_华为手机能将视频设置成来电铃声!原来方法这么简单,学到了...

    华为手机能将视频设置成来电铃声!原来方法这么简单,学到了 华为手机一直受到大家喜爱,因为里面的黑科技功能较多. 那么今天就来带大家了解一下,华为自带的来电秀功能,可以将手机视频设置成来电铃声,好看又有 ...

  9. 画画新手学游戏原画的方法,应该这样学!

    画画新手学游戏原画的方法,应该这样学!CG原画是随着数字绘画发展起来的一种新式的绘画艺术表现形式,与CG原画相匹配的职业师CG原画师.我们经常玩的游戏里,人物角色的设定图就是由CG原画师画出来的.同时 ...

最新文章

  1. Entity Framework Core介绍(1)
  2. 2019河北高职计算机专科学校录取分数线,2019河北高考专科院校录取分数线_专科各院校投档线_一品高考网...
  3. ironpython使用opencv_连这些都不知道,就别说自己懂Python!
  4. [HEOI2012] 朋友圈(最大团 + 结论 + 二分图 + 网络流)
  5. 为什么长视频没有强算法推荐的产品
  6. Chrome截图扩展程序-“截图快手”
  7. [转载] AWS之EMR数据ES通过数据仓库HIVE同步S3
  8. Yii需要php版本,yii框架2.0.9版本发布了
  9. Java基础:查漏补缺
  10. word2vec 使用gensim训练词向量
  11. 【每天学一点新知识】getshell???webshell???
  12. 计算机和网络邻居都不见 了,网上邻居看不到自己和别人电脑怎么办
  13. dell系统重装后无法进入系统_DELL电脑重装系统后出现No bootable devices --strike如何解决...
  14. 散户真的能战胜大庄家么?股市庄家的赚钱手法!
  15. MySQL怎么打开explain_MySql性能加速分析以及PHPMYADMIN中explain用法
  16. python绘图设置时间坐标轴_Matplotlib绘图双纵坐标轴设置及控制设置时间格式
  17. 网易互娱耗时最长的活动
  18. 只有手机号或者身份证能查出来绑定QQ号码?大神请赐教
  19. 使用python实现图像对比度增强
  20. 吴恩达:回顾2021,这些大事件影响了AI这一年

热门文章

  1. html5 字符串对象,JavaScript核心对象-String对象
  2. Spark_UDAF
  3. linux挂载华为存储fc,linux 挂载存储设备
  4. 从零开始学Node.js(二)
  5. 用Python算24点
  6. Expression Design与Blend制作滚动的小球动画教程
  7. 第十三篇:multimap容器和multiset容器中的find操作
  8. 【优达学城测评】SQLite 安装(2)
  9. Design7:数据删除设计
  10. Citrix XenServer 6.5 发布