ex43——基本的面向对象分析和设计

难点在与类Map和Engine的相互调用:

  1. 在Map中先建立字典dict{场景名称:场景类名},
  2. Engine中建立循环,通过实例的返回值(场景名称),建立起与场景类名的相关性,通过场景名称调用将相关类名实例化。
  3. Map中的current、opening、next方法与循环结合后的逻辑性,推动这个文字游戏不断运行。
  4. 此例很好的演示了python面向对象分析和设计的方法。

dict.get(key, default=None)
字典(Dictionary) get() 函数返回指定键的值,如果值不在字典中返回默认值

from sys import exit  # 系统退出用exit
from random import randint   # randint生成随机整数


class Scene():
    # Scene基类,包含所有场景通用信息
    def enter(self):
        print("该场景尚未配置,归为子类并执行enter()")
        exit(1)


class Engine():

    def __init__(self, scene_map):
        self.scene_map = scene_map

    def play(self):
        # 使用方法Map.opening_scene打开当前场景
        current_scene = self.scene_map.opening_scene()

        while True:
            print('\n-------------')
            # 使用方法scene.enter进入下一个场景名称
            next_scene_name = current_scene.enter()
            # 在当前场景进入后,紧接着Map.next_scene载入下一个场景
            current_scene = self.scene_map.next_scene(next_scene_name)


class Death(Scene):
    """死亡场景:在退出之前,随机调出对玩家说一些讽刺的话"""
    # 存入4句讽刺的话
    quips = [
        "You died. You kinda suck at this.",
        "Your mom would be proud ... if she were smarter.",
        "Such a loser.",
        "I have a small puppy that's better at this."
    ]

    def enter(self):
        """方法Death.enter调出讽刺的话,打印到屏幕,并退出程序"""
        print(Death.quips[randint(0, len(self.quips)-1)])
        exit(1)


class CentralCorridor(Scene):

    def enter(self):
        context1 = """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 weapon Armory,
        put it in the bridge, and blow the ship up after getting into an
        escape pod
        \n
        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.
        """
        print(context1)

        action = input("> ")

        if action == "shoot!":
            print("You failed at last")
            return 'death'

        elif action == 'dodge!':
            print("You're caught by alien and failed. ")
            return 'death'

        elif action == 'tell a joke':
            print('You beet the monster and jump through the Weapon Armory door')
            return 'laser_weapon_armory'

        else:
            print("Dose not compute!")
            return 'central_corridor'


class LaserWeaponArmory(Scene):

    def enter(self):
        print('You need to input the code to get the bomb')
        code = ('%d%d%d' % (randint(1, 9), randint(1, 9), randint(1, 9)))
        print('code>',code)
        guess = input("[keypad]> ")
        guesses = 0

        while guess != code and guesses < 10:
            print('Wrong code!')
            guesses += 1
            guess = input('[keypad]>')

        if guess == code:
            print("You got the bomb and run back to the right spot")
            return 'the_bridge'

        else:
            print("bomb explored at last and you died either.")
            return 'death'


class TheBridge(Scene):

    def enter(self):
        print("You surprise 5 alien with a bomb under your arm")

        action = input(">")

        if action == "throw the bomb":
            print("Alien shoot you immediately and you die")
            return 'death'

        elif action == "slowly place the bomb":
            print("You meed escape pod to get off this tin can")
            return 'escape_pod'

        else:
            print("Dose not compute")
            return 'the_bridge'


class EscapePod(Scene):

    def enter(self):
        print("You need to pick one pods to escape. But you don't know which is good.")
        good_pod = randint(1, 5)
        print('good_pod>',good_pod)
        guess = input("[pod #]> ")

        if int(guess) != good_pod:
            print("You choose a broken one, it blast and you died either")
            return 'death'

        else:
            print("You escape with a good pods.")
            print("Congratulations! You win!")
            exit(0)


class Map():

    scenes = {
        'central_corridor': CentralCorridor(),
        'laser_weapon_armory': LaserWeaponArmory(),
        'the_bridge': TheBridge(),
        'escape_pod': EscapePod(),
        'death': Death()
    }

    def __init__(self, start_scene):
        self.start_scene = start_scene

    def next_scene(self, scene_name):
        # dict.get(key, default=None)
        # 字典(Dictionary) get() 函数返回指定键的值,如果值不在字典中返回默认值
        return Map.scenes.get(scene_name)

    def opening_scene(self):
        return self.next_scene(self.start_scene)


a_map = Map('central_corridor')
# Map('central_corridor')后,建立起场景字典,并将实参start_scene设置为central_corridor
# 新建的实例有:
# a_map.start_scene = 'central_corridor'
# a_map.next_scene 返回Map.scenes.get(scene_name),对于本代码,最终返回的是CentralCorridor()
a_game = Engine(a_map)
# 另self.scene_map = a_map
a_game.play()
# a_map.opening_scene() → Map('central_corridor').opening_scene() → 返回值是Map.next_scene(self.start_scene)
# 也可以理解为返回值是Map.next_scene('central_corridor') → 返回值是 Map.scenes.get(scene_name)也可以理解为返回值
# 是Map.scenes.get('central_corridor') → 最终返回是scenes字典中的CentralCorridor().
# 继续开始while循环,进入CentralCorridor()方法中,假如return的是'death'
# self.scene_map.next_scene('death'),其中self.scene_map = scene_map, scene_map = a_map
# 也转化成a_map.next_scene('death'),即Map.scenes.get('death') → 最终返回的是scenes字典中的Death().

有限状态机(Finite-state machine, FSM),又称有限状态自动机,简称状态机,是表示有限个状态以及在这些状态之间的转移和动作等行为的数学模型。FSM是一种算法思想,简单而言,有限状态机由一组状态、一个初始状态、输入和根据输入及现有状态转换为下一个状态的转换函数组成。现实世界中存在大量具有有限个状态的系统:钟表系统、电梯系统、交通信号灯系统、通信协议系统、正则表达式、硬件电路系统设计、软件工程,编译器等,有限状态机的概念就是来自于现实世界中的这些有限系统。https://www.cnblogs.com/21207-iHome/p/6085334.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值