今天看啥  ›  专栏  ›  、Edgar

你真的会对象了吗 -- 用对象实现圣兽决斗凶兽

、Edgar  · 掘金  ·  · 2019-11-17 07:13
阅读 4

你真的会对象了吗 -- 用对象实现圣兽决斗凶兽

在之前的两个小节里面,我们学习了如何定义一个类,以及如何使用类,并且介绍了类的封装,继承,多态等特性,在这一小节里,我们将利用所学的知识来建立一个小小的虚拟斗争游戏类


故事背景:传说在上古时代,有四大凶兽--饕餮,混沌,梼杌和穷奇,同时存在着正义的化身四大神兽--青龙、白虎、朱雀、玄武,他们之间武义相当, 突然有一天四大神兽中的青龙遇上了饕餮,于是他们之间展开了生死决斗,他们分别使用以下技能:
  • 青龙:必杀技飞羽升天攻击力100(10%), 大招神龙摆尾攻击力40(30%),普通攻击10(60%)

  • 饕餮:必杀技冰封绝技攻击力90(15%), 大招吞噬万物攻击力35(30%), 普通攻击20(55%)

假设他们最开始较量的时候血量均为400,那么最后会是谁胜利呢? 要求:

  • 分别定义两个基类 Monster, HolyBeast,中间有类的名称定义(name),攻击方式(attack),血量值HP, 但是HolyBeast自带回血buff,5%的几率回复2%血量,其余均回复10点血量,他们初始血量假设均为400
  • 在基类的基础上定义青龙和饕餮,分别实现其攻击方式
  • 他们之间进行斗争,输出每个回合他们之间的HP值,并进行判断哪一个胜利

首先,第一步,我们应该要定义两个基类,利用之前介绍过的封装特性以及抽象类和抽象函数的定义 ,我们可以十分简单的写出下面的代码:

import random


class Monster(metaclass=ABCMeta):
    """
    凶兽的基类,为抽象类
    """
    def __init__(self, name):
        """初始化凶兽的名称,血量"""
        self._name = name
        self._HP = 400

    @property
    def HP(self):
        return self._HP

    @HP.setter
    def HP(self, HP):
        self._HP = HP 

    @property
    def name(self):
        return self._name

    @abstractmethod
    def attack(self):
        """抽象的方法"""
        pass 

    def alive(self):
        return self._HP > 0 


class HolyBeast(metaclass=ABCMeta):
    def __init__(self, name):
        """初始化圣兽的名称,血量"""
        self._name = name 
        self._HP = 400
    
    @property
    def HP(self):
        return self._HP

    @HP.setter
    def HP(self, HP):
        self._HP = HP

    @property
    def name(self):
        return self._name

    @abstractmethod
    def attack(self):
        pass

    def resume(self):
        """自我恢复,使用随机模块来判定几率大小"""
        rand = random.random()
        if rand > 0.95:
            self._HP += int(0.02*self._HP)
        else:
            self.HP += 10

    def alive(self):
        return self._HP > 0
复制代码

在上面的代码中,我们定义了两个基类,Monster表示凶兽,HolyBeast表示圣兽,运用所讲过的装饰器,我们将类中的属性进行封装并向外提高接口;使用abstractmethod我们将其定义成抽象方法,并由子类提供实现,在HolyBeast中我们使用random模块生成的随机生成的数字进行概率判断,并回复其血量


接下来,我们将利用上面的两个基类进行扩展,在其基础之上加上子类所需要的方法,我们写来看看饕餮如何实现吧


class TaoTie(Monster):
    def __init__(self, name):
        """调用父类的初始化方法"""
        super().__init__(name)

    def attack(self):
        """实现攻击时所攻击的血量,其余功能由beat实现"""
        rand = random.random()
        if rand > 0.85:
            kill_blood = 90 
        elif rand > 0.55:
            kill_blood = 35
        else:
            kill_blood = 20
        return kill_blood

    def beat(self, other):
        kill_blood = self.attack()
        print("凶兽{} 击杀 圣兽{} {} HP".format(self.name, other.name, kill_blood))
        other.HP -= kill_blood

复制代码

首先我们调用父类的初始化方法,对子类进行初始化,然后attack方法实现获取攻击消耗对方的血量,最后由beat函数调用attack函数并实现攻击,并同时消耗对方的血量,同理,我们可以写出QingLong类,只是需要注意在其攻击之后要使用恢复技能即可


class QingLong(HolyBeast):
    def __init__(self, name):
        super().__init__(name)

    def attack(self):
        rand = random.random()
        if rand > 0.9:
            kill_blood = 100
        elif rand > 0.6:
            kill_blood = 40 
        else:
            kill_blood = 10 
        return kill_blood

    def beat(self, other):
        kill_blood = self.attack()
        print("圣兽{} 击杀 凶兽{} {} HP".format(self.name, other.name, kill_blood))
        other.HP -= kill_blood
        self.resume()
复制代码

这样,我们便已经定义好了我们需要的类了,于是接下来,我们便需要实现其相互绝斗的部分了。

当然第一步,我们应该实例化具体对象,然后利用对象的beat方法实现决斗,当其中一个血量消耗完全的时候,我们便不再进行,所以我们可采用while循环来实现这一点,并在循环中输出相关的血量信息,回合次数,我们在把他们包装到main函数里面即可, 代码如下:


def main():
    ql = QingLong("青龙")
    tt = TaoTie("饕餮")
    num = 0
    while ql.alive() and tt.alive():
        ql.beat(tt)
        tt.beat(ql)
        if ql.alive() and tt.alive():
            print("-----------回合{}------------".format(num))
            print("{}血量为:{},{}血量为:{}".format(ql.name, ql.HP, tt.name, tt.HP))
            time.sleep(0.5)
        else:
            print("")
            if ql.alive():
                print("{}血量为:{},{}血量为:0".format(ql.name, ql.HP, tt.name))
                print(">{}< 胜利".format(ql.name))
            else:
                print("{}血量为:0,{}血量为:{}".format(ql.name, tt.name, tt.HP))
                print(">{}< 胜利".format(tt.name))
        num += 1
复制代码

在最后我们只需要调用main函数,便可以实现青龙和饕餮之间的决斗了,完整代码发送fight到公众号后台获取下载链接

wechat



原文地址:访问原文地址
快照地址: 访问文章快照