• 大爽Python入门教程 74 实践演示 控制台版本——简易回合战斗


    大爽Python入门公开课教案 点击查看教程总目录

    1 背景介绍

    不知道大家有没有玩过魔塔。
    在我小时候,这是一个很经典又好玩的小游戏。

    其实最早想做一个控制台版本的简易魔塔。
    后来发现控制台实现的效果实在是不理想,而且耗费的精力又颇大。
    总的来讲,就是费力不讨好。

    所以做了更进一步的简化,用控制台只实现简化了的回合战斗。

    功能大概有两处:

    1. 输入命令,获取玩家信息或者退出游戏。
    2. 输入敌人,让玩家和敌人战斗,将战斗结果展示出来。

    2 详细说明

    玩家和敌人都属于人,有以下三个基本属性(以下建成三维)

    • 血量: hp
    • 攻击力: attack
    • 防御力: defence

    都有一个基本方法

    • 打击(攻击): hit
      攻击的基本计算方式为: 伤害 = 自己攻击力 - 对手防御力
      伤害为正时,扣除敌人对应血量。

    • 是否存活: is_alive
      即血量大于 0

    玩家特有属性

    • 等级: lv
      初始等级为1。
      每升一级,血量恢复。三维翻倍。
    • 经验: exp
      该值分两部分,一个是当前经验,一个是升级经验。
      当前经验够升级时,扣除升级经验并升级。
      每升一级,所需升级经验翻倍。

    敌人特有方法

    • 经验掉落: drop_exp
      该方法返回经验值,战胜敌人即可获得该经验值。

    敌人分三档

    • 普通敌人
    • 高级敌人: 攻击时,无视玩家防御(即伤害=攻击力)
    • BOSS: 攻击时,无视玩家防御(即伤害=攻击力),还能自己回血(回血量=伤害量)

    数值设置

    这个可以自由发挥
    我这里的设置如下

    玩家

    hp, attack, defence = 100, 10, 5
    exp = 0 / 20
    

    普通敌人

    hp, attack, defence = 50, 10, 5
    

    掉落经验值:10

    高级敌人

    hp, attack, defence = 100, 20, 10
    

    掉落经验值:20

    BOSS

    hp, attack, defence = 200, 40, 20
    

    掉落经验值:40

    游戏流程

    运行游戏,先展示欢迎信息。

    Welcome to my game.
    

    再展示玩家信息

    ======= Player status ========
    HP: 100 / 100
    Attack: 10
    Defence: 10
    Lv: 1. EXP: 0/ 20
    ==============================
    

    接着提醒用户输入

    Enter your command:
    

    玩家可以输入命令,或者敌人

    可解析的命令如下

    • s: 展示玩家信息
    • q: 退出游戏

    退出游戏时,输出如下

    Bye.
    

    可解析的敌人如下

    • e: Enemy,普通敌人
    • a: AdvancedEnemy, 高级敌人
    • b: Boss, 老怪

    输入敌人,则让玩家和敌人战斗,
    战斗流程是,玩家先攻击敌人,然后敌人再攻击玩家,直至一方死亡。

    战胜敌人时,输出战胜信息如下(包括敌人种类,获得经验,当前经验,剩余血量)
    (比如战胜普通敌人)

    Defeat enemy: Enemy. Gain exp: 10. Current exp: 10 / 20. Left hp: 55
    

    战斗过程中,如果有升级,则输出升级信息如下

    You upgraded, current level: 2, current hp: 200.
    

    战斗失败,输出失败信息如下,且结束游戏

    You lost. Boss's left hp: 100
    

    可以一次输入多个敌人,玩家从前往后依次战斗。

    运行效果

    输入分别是

    e
    e
    a
    b
    

    运行效果如下

    Welcome to my game.
    ======= Player status ========
    HP: 100 / 100
    Attack: 10
    Defence: 10
    Lv: 1. EXP: 0/ 20
    ==============================
    Enter your command:e
    Defeat enemy: Enemy. Gain exp: 10. Current exp: 10 / 20. Left hp: 55
    Enter your command:e
    Defeat enemy: Enemy. Gain exp: 10. Current exp: 20 / 20. Left hp: 10
    You upgraded, current level: 2, current hp: 200.
    Enter your command:a
    Defeat enemy: AdvancedEnemy. Gain exp: 20. Current exp: 20 / 40. Left hp: 20
    Enter your command:s
    ======= Player status ========
    HP: 20 / 200
    Attack: 20
    Defence: 20
    Lv: 2. EXP: 20/ 40
    ==============================
    Enter your command:b
    You lost. Boss's left hp: 240
    

    3 分析

    类的构思

    首先需要实现一个基础的人物类Person
    然后继承Person实现玩家类Player
    之后继承Person实现敌人类:
    EnemyAdvancedEnemyBoss

    人物类就这些。
    最后将游戏的处理也放在一个类Game里去进行。

    初步架构

    class Person:
        pass
    
    class Player(Person):
        pass
    
    class Enemy(Person):
        pass
    
    class AdvancedEnemy(Enemy):
        pass
    
    class Boss(Enemy):
        pass
    
    class Game:
        pass
    

    4 逐步实现

    基础类Person

    代码如下

    class Person:
        def __init__(self, hp, attack, defence):
            self.hp = hp
            self.attack = attack
            self.defence = defence
    
        def hit(self, other):
            damage = self.attack - other.defence
            if damage > 0:
                other.hp -= damage
    
        def is_alive(self):
            return self.hp > 0
    

    玩家类Player

    class Player(Person):
        def __init__(self):
            hp, attack, defence = 100, 10, 5
            super().__init__(hp, attack, defence)
    
            self.lv = 1
            self.base_hp = self.hp  # base_hp: 当前等级总HP, 升级时是这个翻倍
            self.exp = [0, 20]  # 第一个是现有经验,第二个是升级需要的总经验。
    
        def show_info(self):
            """
            展示玩家信息。
            效果示例如下:
            ======= Player status ========
            HP: 20 / 200
            Attack: 20
            Defence: 20
            Lv: 2. EXP: 20/ 40
            ==============================
            """
            print("{:=^30s}".format(" Player status "))
            print("HP: %s / %s" % (self.hp, self.base_hp))
            print("Attack: %s" % self.attack)
            print("Defence: %s" % self.attack)
            print("Lv: %s. EXP: %s / %s" % (self.lv, self.exp[0], self.exp[1]))
            print("=" * 30)
    
        def win(self, enemy):
            exp = enemy.drop_exp()
            self.exp[0] += enemy.drop_exp()
            print("Defeat enemy: %s. Gain exp: %s. Current exp: %s / %s. Left hp: %s" %
                  (enemy.__class__.__name__, exp, self.exp[0], self.exp[1] ,self.hp))
    
            if self.exp[0] >= self.exp[1]:
                self.exp[0] -= self.exp[1]  # 升级时扣除升级需要的经验
                self.lv_up()
    
        def lv_up(self):
            self.exp[1] = self.exp[1] * 2  # 每升一级,升级时需要的经验翻倍
            self.lv += 1
    
            # 每升一级,三维翻倍
            self.base_hp = self.base_hp * 2
            self.attack = self.attack * 2
            self.defence = self.defence * 2
    
            # 升级后,恢复满血
            self.hp = self.base_hp
            print("You upgraded, current level: %s, current hp: %s." % (self.lv, self.hp))
    
        def lose(self, enemy):
            print("You lost. %s's left hp: %s" % (enemy.__class__.__name__, enemy.hp))
    

    其中,有这样一个语法

    enemy.__class__.__name__
    

    enemy.__class__: 作用是得到enemy这个对象object的类__class__
    class.__name__: 作用是得到一个类class的名字(字符串形式)

    使用示例如下

    class AAA:
        pass
    
    a = AAA()
    print(a.__class__)
    print(a.__class__ == AAA)
    print(a.__class__.__name__)
    print(AAA.__name__)
    

    输出为

    <class '__main__.AAA'>
    True
    AAA
    AAA
    

    敌人类

    三种敌人代码如下
    Enemy

    class Enemy(Person):
        def __init__(self, base=1):
            hp, attack, defence = 50 * base, 10 * base, 5 * base
            super().__init__(hp, attack, defence)
    
            self.exp = 10 * base
    
        def drop_exp(self):
            return self.exp
    

    AdvancedEnemy

    class AdvancedEnemy(Enemy):
        def __init__(self):
            super().__init__(base=2)
    
        def hit(self, other):
            damage = self.attack
            if damage > 0:
                other.hp -= damage
    

    Boss

    class Boss(Enemy):
        def __init__(self):
            super().__init__(base=4)
    
        def hit(self, other):
            damage = self.attack
            if damage > 0:
                other.hp -= damage
                self.hp += damage
    

    游戏类Game

    class Game:
        def __init__(self):
            self.player = Player()
    
        def run(self):
            print("Welcome to my game.")
            self.player.show_info()
            while True:
                cmd = input("Enter your command:")
                cmd = cmd.lower()
                if cmd == "s":
                    self.player.show_info()
                elif cmd == "q":
                    print("Bye")
                    return
                else:
                    self.handle_commands(cmd)
    
        def handle_commands(self, cmd):
            for c in cmd:
                if c == "e":
                    enemy = Enemy()
                elif c == "a":
                    enemy = AdvancedEnemy()
                elif c == "b":
                    enemy = Boss()
                else:
                    print("Invalid Input.")
                    return
    
                self.fight(enemy)
    
        def fight(self, enemy):
            while True:
                self.player.hit(enemy)
                if not enemy.is_alive():
                    self.player.win(enemy)
                    return
    
                enemy.hit(self.player)
                if not self.player.is_alive():
                    self.player.lose(enemy)
                    exit()
    

    调用

    调用起来非常简单

    game = Game()
    game.run()
    

    4 优化

    Game类的handle_commands(self, cmd)方法中,
    条件判断有些罗嗦,如果敌人类增加,则又要增加。

    有的语言有case语法,能简化这里。
    python虽然没有这个语法,但是有办法实现对应效果,甚至更简单。

    优化方法如下
    先在之前的空白处添加变量enemy_map如下

    enemy_map = {
        "e": Enemy,
        "a": AdvancedEnemy,
        "b": Boss,
    }
    

    再修改handle_commands(self, cmd)方法如下

    def handle_commands(self, cmd):
        for c in cmd:
            if c in enemy_map:
                enemy_class = enemy_map[c]
                enemy = enemy_class()
                self.fight(enemy)
            else:
                print("Invalid Input.")
                return
    

    5 总代码

    最后总代码如下

    class Person:
        def __init__(self, hp, attack, defence):
            self.hp = hp
            self.attack = attack
            self.defence = defence
    
        def hit(self, other):
            damage = self.attack - other.defence
            if damage > 0:
                other.hp -= damage
    
        def is_alive(self):
            return self.hp > 0
    
    
    class Player(Person):
        def __init__(self):
            hp, attack, defence = 100, 10, 5
            super().__init__(hp, attack, defence)
    
            self.lv = 1
            self.base_hp = self.hp  # base_hp: 当前等级总HP, 升级时是这个翻倍
            self.exp = [0, 20]  # 第一个是现有经验,第二个是升级需要的总经验。
    
        def show_info(self):
            """
            展示玩家信息。
            效果示例如下:
            ======= Player status ========
            HP: 20 / 200
            Attack: 20
            Defence: 20
            Lv: 2. EXP: 20/ 40
            ==============================
            """
            print("{:=^30s}".format(" Player status "))
            print("HP: %s / %s" % (self.hp, self.base_hp))
            print("Attack: %s" % self.attack)
            print("Defence: %s" % self.attack)
            print("Lv: %s. EXP: %s / %s" % (self.lv, self.exp[0], self.exp[1]))
            print("=" * 30)
    
        def win(self, enemy):
            exp = enemy.drop_exp()
            self.exp[0] += enemy.drop_exp()
            print("Defeat enemy: %s. Gain exp: %s. Current exp: %s / %s. Left hp: %s" %
                  (enemy.__class__.__name__, exp, self.exp[0], self.exp[1], self.hp))
    
            if self.exp[0] >= self.exp[1]:
                self.exp[0] -= self.exp[1]  # 升级时扣除升级需要的经验
                self.lv_up()
    
        def lv_up(self):
            self.exp[1] = self.exp[1] * 2  # 每升一级,升级时需要的经验翻倍
            self.lv += 1
    
            # 每升一级,三维翻倍
            self.base_hp = self.base_hp * 2
            self.attack = self.attack * 2
            self.defence = self.defence * 2
    
            # 升级后,恢复满血
            self.hp = self.base_hp
            print("You upgraded, current level: %s, current hp: %s." % (self.lv, self.hp))
    
        def lose(self, enemy):
            print("You lost. %s's left hp: %s" % (enemy.__class__.__name__, enemy.hp))
    
    
    class Enemy(Person):
        def __init__(self, base=1):
            hp, attack, defence = 50 * base, 10 * base, 5 * base
            super().__init__(hp, attack, defence)
    
            self.exp = 10 * base
    
        def drop_exp(self):
            return self.exp
    
    
    class AdvancedEnemy(Enemy):
        def __init__(self):
            super().__init__(base=2)
    
        def hit(self, other):
            damage = self.attack
            if damage > 0:
                other.hp -= damage
    
    
    class Boss(Enemy):
        def __init__(self):
            super().__init__(base=4)
    
        def hit(self, other):
            damage = self.attack
            if damage > 0:
                other.hp -= damage
                self.hp += damage
    
    
    enemy_map = {
        "e": Enemy,
        "a": AdvancedEnemy,
        "b": Boss,
    }
    
    
    class Game:
        def __init__(self):
            self.player = Player()
    
        def run(self):
            print("Welcome to my game.")
            self.player.show_info()
            while True:
                cmd = input("Enter your command:")
                cmd = cmd.lower()
                if cmd == "s":
                    self.player.show_info()
                elif cmd == "e":
                    print("Bye")
                    return
                else:
                    self.handle_commands(cmd)
    
        def handle_commands(self, cmd):
            for c in cmd:
                if c in enemy_map:
                    enemy_class = enemy_map[c]
                    enemy = enemy_class()
                    self.fight(enemy)
                else:
                    print("Invalid Input.")
                    return
    
        def fight(self, enemy):
            while True:
                self.player.hit(enemy)
                if not enemy.is_alive():
                    self.player.win(enemy)
                    return
    
                enemy.hit(self.player)
                if not self.player.is_alive():
                    self.player.lose(enemy)
                    exit()
    
    
    game = Game()
    game.run()
    
  • 相关阅读:
    老板也是一个工种,也是一种技能
    用上了ReSharper
    《钟馗伏魔:雪妖魔灵》另类解读
    内部培训-流程图培训
    未来价值是把信息从网上拿下来,而不是放上
    一个人的电影
    2015清明节假期纪实
    十年魔戒
    天使基金资金预期使用表
    项目过程中各阶段应交付的文档
  • 原文地址:https://www.cnblogs.com/BigShuang/p/15738345.html
Copyright © 2020-2023  润新知