import random# 1. 元类:追踪所有角色类的创建
class MetaCharacter(type):"""元类:记录所有角色类并自动添加种族标识"""character_types = [] # 存储所有角色类def __new__(cls, name: str, bases: tuple, namespace: dict):new_cls = super().__new__(cls, name, bases, namespace)if name != "BaseCharacter": # 排除基类cls.character_types.append(new_cls)print(f"元类创建角色类: {name}")return new_cls# 2. 基类:所有角色的抽象基类,由元类MetaCharacter创建
class BaseCharacter(metaclass=MetaCharacter):"""角色基类,定义核心属性与行为"""__slots__ = ("_name", "_hp", "_attack", "_defense") # 限制动态属性race: str = "Unknown" # 类属性:种族标识default_hp: int = 100 # 类属性:默认生命值 hp的全称为health points default_attack: int = 10 # 类属性:默认攻击力default_defense: int = 5 # 类属性:默认防御力 def __init__(self, name: str):# 私有属性:名称、生命值、攻击力、防御力self._name = name.strip() # 移除首尾空格,标准化名称 self._hp = self.default_hp # 初始化生命值为默认值self._attack = self.default_attack # 初始化攻击力为默认值self._defense = self.default_defense # 初始化防御力为默认值# 封装:属性访问控制@propertydef name(self) -> str:return self._name@propertydef hp(self) -> int:return self._hp@hp.setter # 生命值 setter 方法,确保非负def hp(self, value: int):self._hp = max(0, value) # 确保生命值不为负@propertydef attack(self) -> int:return self._attack@attack.setter # 攻击力 setter 方法,确保非负def attack(self, value: int):if value < 0:raise ValueError("攻击力不能为负")self._attack = value# 类方法:批量设置种族默认属性@classmethoddef set_race_defaults(cls, hp: int, attack: int, defense: int): # 生命值、攻击力、防御力的默认值cls.default_hp = hpcls.default_attack = attackcls.default_defense = defenseprint(f"[{cls.race}] 种族默认属性更新: HP={hp}, 攻击={attack}, 防御={defense}")# 静态方法:伤害计算工具@staticmethoddef calculate_damage(attacker: 'BaseCharacter', defender: 'BaseCharacter') -> int:base_damage = max(1, attacker.attack - defender._defense // 2)# 生命值低于30%时伤害加成if defender.hp < defender.default_hp * 0.3:base_damage = int(base_damage * 1.5)return base_damage# 核心方法:攻击目标(多态基础)def attack_target(self, target: 'BaseCharacter'):if self.hp <= 0:print(f"{self.name}已倒下,无法攻击!")returnif target.hp <= 0: print(f"{target.name}已被击败,无需攻击!")return# 只要目标生命值大于0,就可以攻击damage = self.calculate_damage(self, target)target.hp -= damageprint(f"{self.name}攻击了{target.name},造成{damage}点伤害!")if target.hp <= 0:print(f"{target.name}被击败了!")# 特殊方法:字符串表示def __str__(self) -> str:return f"{self.race} {self.name} | HP: {self.hp}/{self.default_hp} | 攻击: {self.attack} | 防御: {self._defense}"# 特殊方法:角色组合(组队)def __add__(self, other: 'BaseCharacter') -> 'Team':if not isinstance(other, BaseCharacter):raise TypeError("只能与角色组队")return Team([self, other])# 特殊方法:调用实例使用技能def __call__(self, skill: 'BaseSkill'): # 鸭子类型:只要有cast方法即可if self.hp <= 0:print(f"{self.name}无法使用技能(已倒下)")returnskill.cast(self) # 调用技能的cast方法,返回伤害值# 3. 类装饰器:添加临时增益效果
def temporary_buff(bonus_hp: int = 0, bonus_attack: int = 0):"""类装饰器:为角色添加临时属性加成(兼容 __slots__,不新增实例字段)"""def decorator(cls):original_init = cls.__init__def new_init(self, *args, **kwargs):# 先调用原始初始化,确保已有的 __slots__ 字段就绪original_init(self, *args, **kwargs)# 直接将加成体现在现有的基础属性上,避免新增字段触发 __slots__ 限制self.hp += bonus_hpself.attack = self.attack + bonus_attackprint(f"{self.name}获得临时增益: HP+{bonus_hp}, 攻击+{bonus_attack}")# 不重写 attack property,避免访问不存在的 _bonus_attack 字段cls.__init__ = new_initreturn clsreturn decorator# 4. 武器类(组合关系:角色持有武器)
class Weapon:"""武器类,与角色形成组合关系"""__slots__ = ("_name", "_damage", "_durability") # 限制属性def __init__(self, name: str, damage: int, durability: int = 100):self._name = nameself._damage = damageself._durability = durability@propertydef name(self) -> str:return self._name@propertydef damage(self) -> int:return self._damage if self._durability > 0 else 0@propertydef durability(self) -> int:return self._durabilitydef use(self) -> int:"""使用武器,消耗耐久度"""if self._durability <= 0:print(f"{self.name}已损坏,无法使用!")return 0self._durability = max(0, self._durability - 10)return self._damagedef __str__(self) -> str:return f"[{self.name} 伤害:{self.damage} 耐久:{self.durability}%]"# 5. 人类类(继承+多态+组合)
@temporary_buff(bonus_hp=20, bonus_attack=3) # 应用类装饰器
class Human(BaseCharacter):"""人类角色类"""race = "Human"__slots__ = ("_intelligence", "_weapon") # 扩展基类slotsdef __init__(self, name: str, intelligence: int = 5, weapon: Weapon = None):super().__init__(name) # 调用父类构造self._intelligence = intelligence# 组合关系:人类必须持有武器(默认拳头)self._weapon = weapon or Weapon("拳头", 2)@propertydef intelligence(self) -> int:return self._intelligence@intelligence.setterdef intelligence(self, value: int):self._intelligence = max(0, value)@propertydef weapon(self) -> Weapon:return self._weapon# 多态:重写攻击方法(使用武器)def attack_target(self, target: BaseCharacter):weapon_damage = self._weapon.use()original_attack = self.attackself.attack += weapon_damage # 临时叠加武器伤害super().attack_target(target) # 调用父类攻击逻辑self.attack = original_attack # 恢复原始攻击print(f"[{self.weapon}]造成额外{weapon_damage}点伤害")def __str__(self) -> str:base_str = super().__str__()return f"{base_str} | 智力: {self._intelligence} | 武器: {self._weapon}"# 6. 狗类(继承+多态)
class Dog(BaseCharacter):"""狗角色类"""race = "Dog"__slots__ = ("_agility", "_breed") # 扩展属性def __init__(self, name: str, breed: str = "普通犬", agility: int = 8):super().__init__(name)self._agility = agilityself._breed = breed@propertydef agility(self) -> int:return self._agility@agility.setterdef agility(self, value: int):self._agility = max(0, value)# 多态:重写攻击方法(敏捷影响暴击)def attack_target(self, target: BaseCharacter):# 敏捷越高,暴击概率越高crit_prob = self._agility / 20is_crit = random.random() < crit_proboriginal_attack = self.attackif is_crit:self.attack *= 2print(f"{self.name}触发暴击!攻击翻倍!")super().attack_target(target)self.attack = original_attack # 恢复def __str__(self) -> str:base_str = super().__str__()return f"{base_str} | 品种: {self._breed} | 敏捷: {self._agility}"# 7. 技能系统(鸭子类型)
class BaseSkill:"""技能基类,定义鸭子类型接口"""def __init__(self, name: str, cost: int = 10):self.name = nameself.cost = cost # 技能消耗(生命值)def cast(self, caster: BaseCharacter) -> int: # 施法逻辑(必须实现) """施法逻辑(必须实现)"""raise NotImplementedError("技能必须实现cast方法")class FireballSkill(BaseSkill): """火球术(人类专属)"""def __init__(self):super().__init__("火球术", cost=15)def cast(self, caster: BaseCharacter) -> int: # 施法逻辑(必须实现)"""施法逻辑(必须实现)"""if not isinstance(caster, Human):print(f"{caster.name}无法使用火球术(非人类)")returnif caster.hp < self.cost:print(f"{caster.name}生命值不足,无法释放{self.name}")return# 消耗生命值,伤害与智力相关caster.hp -= self.costdamage = 20 + caster.intelligence * 3print(f"{caster.name}释放{self.name},消耗{self.cost}HP,造成{damage}点火焰伤害!")return damageclass BiteSkill(BaseSkill):"""撕咬(狗专属)"""def __init__(self):super().__init__("疯狂撕咬", cost=5)def cast(self, caster: BaseCharacter) -> int: # 施法逻辑(必须实现)"""施法逻辑(必须实现)""" if not isinstance(caster, Dog):print(f"{caster.name}无法使用撕咬(非犬类)")returnif caster.hp < self.cost:print(f"{caster.name}生命值不足,无法释放{self.name}")return# 消耗生命值,伤害与敏捷相关caster.hp -= self.costdamage = 15 + caster.agility * 2print(f"{caster.name}使用{self.name},消耗{self.cost}HP,造成{damage}点撕裂伤害!")return damage# 8. 队伍类(聚合关系)
class Team:"""队伍类,聚合多个角色(角色可属于多个队伍)"""def __init__(self, members): # members 队伍成员列表self.members = membersdef __str__(self) -> str:return f"队伍成员: {[m.name for m in self.members]}"def is_defeated(self) -> bool:"""判断队伍是否全灭"""return all(m.hp <= 0 for m in self.members)def attack(self, enemy_team: 'Team'):"""队伍攻击另一队伍(支持技能释放)"""if self.is_defeated():print("己方队伍已全灭,无法攻击!")returnif enemy_team.is_defeated():print("敌方队伍已全灭,无需攻击!")returnprint("\n----- 队伍交锋 -----")for attacker in self.members:if attacker.hp <= 0:continue# 随机选择敌方目标targets = [e for e in enemy_team.members if e.hp > 0]if not targets:continuetarget = random.choice(targets)used_skill = False# 概率释放各自专属技能if isinstance(attacker, Human) and random.random() < 0.4:damage = FireballSkill().cast(attacker)if isinstance(damage, int) and damage > 0:target.hp -= damageprint(f"{attacker.name}用技能对{target.name}造成{damage}点伤害!")if target.hp <= 0:print(f"{target.name}被击败了!")used_skill = Trueelif isinstance(attacker, Dog) and random.random() < 0.5:damage = BiteSkill().cast(attacker)if isinstance(damage, int) and damage > 0:target.hp -= damageprint(f"{attacker.name}用技能对{target.name}造成{damage}点伤害!")if target.hp <= 0:print(f"{target.name}被击败了!")used_skill = Trueif not used_skill:attacker.attack_target(target)# 9. 战斗系统(关联关系)
class Battle:"""战斗场景,关联多个角色/队伍"""def __init__(self, team1: Team, team2: Team):self.team1 = team1self.team2 = team2self.round = 0def start(self, max_rounds: int = 5):"""开始战斗,最多进行max_rounds回合"""print("\n===== 人狗大战 正式开始 =====")while self.round < max_rounds:self.round += 1print(f"\n===== 第{self.round}回合 =====")# 随机决定先手if random.random() < 0.5:self.team1.attack(self.team2)if self.team2.is_defeated():breakself.team2.attack(self.team1)else:self.team2.attack(self.team1)if self.team1.is_defeated():breakself.team1.attack(self.team2)# 检查是否有队伍全灭if self.team1.is_defeated() or self.team2.is_defeated():break# 战斗结果print("\n===== 战斗结束 =====")if self.team1.is_defeated():print("狗队获胜!")elif self.team2.is_defeated():print("人类队获胜!")else:print("平局!")# 打印最终状态print("\n【最终状态】")for m in self.team1.members + self.team2.members:print(m)# 测试代码
if __name__ == "__main__":# 配置种族默认属性Human.set_race_defaults(hp=150, attack=12, defense=8)Dog.set_race_defaults(hp=120, attack=15, defense=5)# 创建武器sword = Weapon("精铁剑", 10, durability=90)axe = Weapon("巨斧", 15, durability=60)# 创建角色alice = Human("Alice", intelligence=9, weapon=sword)bob = Human("Bob", intelligence=6, weapon=axe)dog1 = Dog("大黄", breed="藏獒", agility=12)dog2 = Dog("小黑", breed="狼犬", agility=10)# 打印初始状态print("\n【初始状态】")print(alice)print(bob)print(dog1)print(dog2)# 测试组队(__add__方法)team_human = alice + bobteam_dog = dog1 + dog2print(f"\n{team_human}")print(f"{team_dog}")# 测试技能使用(__call__方法)print("\n【技能测试】")alice(FireballSkill()) # alice使用火球术dog1(BiteSkill()) # dog1使用撕咬# 开始战斗battle = Battle(team_human, team_dog)battle.start(max_rounds=4)