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 # 初始化防御力为默认值
# 封装:属性访问控制
@property
def name(self) -> str:
return self._name
@property
def hp(self) -> int:
return self._hp
@hp.setter # 生命值 setter 方法,确保非负
def hp(self, value: int):
self._hp = max(0, value) # 确保生命值不为负
@property
def attack(self) -> int:
return self._attack
@attack.setter # 攻击力 setter 方法,确保非负
def attack(self, value: int):
if value < 0:
raise ValueError("攻击力不能为负")
self._attack = value
# 类方法:批量设置种族默认属性
@classmethod
def set_race_defaults(cls, hp: int, attack: int, defense: int): # 生命值、攻击力、防御力的默认值
cls.default_hp = hp
cls.default_attack = attack
cls.default_defense = defense
print(f"[{cls.race}] 种族默认属性更新: HP={hp}, 攻击={attack}, 防御={defense}")
# 静态方法:伤害计算工具
@staticmethod
def 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}已倒下,无法攻击!")
return
if target.hp <= 0:
print(f"{target.name}已被击败,无需攻击!")
return
# 只要目标生命值大于0,就可以攻击
damage = self.calculate_damage(self, target)
target.hp -= damage
print(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}无法使用技能(已倒下)")
return
skill.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_hp
self.attack = self.attack + bonus_attack
print(f"{self.name}获得临时增益: HP+{bonus_hp}, 攻击+{bonus_attack}")
# 不重写 attack property,避免访问不存在的 _bonus_attack 字段
cls.__init__ = new_init
return cls
return decorator
# 4. 武器类(组合关系:角色持有武器)
class Weapon:
"""武器类,与角色形成组合关系"""
__slots__ = ("_name", "_damage", "_durability") # 限制属性
def __init__(self, name: str, damage: int, durability: int = 100):
self._name = name
self._damage = damage
self._durability = durability
@property
def name(self) -> str:
return self._name
@property
def damage(self) -> int:
return self._damage if self._durability > 0 else 0
@property
def durability(self) -> int:
return self._durability
def use(self) -> int:
"""使用武器,消耗耐久度"""
if self._durability <= 0:
print(f"{self.name}已损坏,无法使用!")
return 0
self._durability = max(0, self._durability - 10)
return self._damage
def __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") # 扩展基类slots
def __init__(self, name: str, intelligence: int = 5, weapon: Weapon = None):
super().__init__(name) # 调用父类构造
self._intelligence = intelligence
# 组合关系:人类必须持有武器(默认拳头)
self._weapon = weapon or Weapon("拳头", 2)
@property
def intelligence(self) -> int:
return self._intelligence
@intelligence.setter
def intelligence(self, value: int):
self._intelligence = max(0, value)
@property
def weapon(self) -> Weapon:
return self._weapon
# 多态:重写攻击方法(使用武器)
def attack_target(self, target: BaseCharacter):
weapon_damage = self._weapon.use()
original_attack = self.attack
self.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 = agility
self._breed = breed
@property
def agility(self) -> int:
return self._agility
@agility.setter
def agility(self, value: int):
self._agility = max(0, value)
# 多态:重写攻击方法(敏捷影响暴击)
def attack_target(self, target: BaseCharacter):
# 敏捷越高,暴击概率越高
crit_prob = self._agility / 20
is_crit = random.random() < crit_prob
original_attack = self.attack
if is_crit:
self.attack *= 2
print(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 = name
self.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}无法使用火球术(非人类)")
return
if caster.hp < self.cost:
print(f"{caster.name}生命值不足,无法释放{self.name}")
return
# 消耗生命值,伤害与智力相关
caster.hp -= self.cost
damage = 20 + caster.intelligence * 3
print(f"{caster.name}释放{self.name},消耗{self.cost}HP,造成{damage}点火焰伤害!")
return damage
class BiteSkill(BaseSkill):
"""撕咬(狗专属)"""
def __init__(self):
super().__init__("疯狂撕咬", cost=5)
def cast(self, caster: BaseCharacter) -> int: # 施法逻辑(必须实现)
"""施法逻辑(必须实现)"""
if not isinstance(caster, Dog):
print(f"{caster.name}无法使用撕咬(非犬类)")
return
if caster.hp < self.cost:
print(f"{caster.name}生命值不足,无法释放{self.name}")
return
# 消耗生命值,伤害与敏捷相关
caster.hp -= self.cost
damage = 15 + caster.agility * 2
print(f"{caster.name}使用{self.name},消耗{self.cost}HP,造成{damage}点撕裂伤害!")
return damage
# 8. 队伍类(聚合关系)
class Team:
"""队伍类,聚合多个角色(角色可属于多个队伍)"""
def __init__(self, members): # members 队伍成员列表
self.members = members
def __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("己方队伍已全灭,无法攻击!")
return
if enemy_team.is_defeated():
print("敌方队伍已全灭,无需攻击!")
return
print("\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:
continue
target = 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 -= damage
print(f"{attacker.name}用技能对{target.name}造成{damage}点伤害!")
if target.hp <= 0:
print(f"{target.name}被击败了!")
used_skill = True
elif isinstance(attacker, Dog) and random.random() < 0.5:
damage = BiteSkill().cast(attacker)
if isinstance(damage, int) and damage > 0:
target.hp -= damage
print(f"{attacker.name}用技能对{target.name}造成{damage}点伤害!")
if target.hp <= 0:
print(f"{target.name}被击败了!")
used_skill = True
if not used_skill:
attacker.attack_target(target)
# 9. 战斗系统(关联关系)
class Battle:
"""战斗场景,关联多个角色/队伍"""
def __init__(self, team1: Team, team2: Team):
self.team1 = team1
self.team2 = team2
self.round = 0
def start(self, max_rounds: int = 5):
"""开始战斗,最多进行max_rounds回合"""
print("\n===== 人狗大战 正式开始 =====")
while self.round < max_rounds:
self.round += 1
print(f"\n===== 第{self.round}回合 =====")
# 随机决定先手
if random.random() < 0.5:
self.team1.attack(self.team2)
if self.team2.is_defeated():
break
self.team2.attack(self.team1)
else:
self.team2.attack(self.team1)
if self.team1.is_defeated():
break
self.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 + bob
team_dog = dog1 + dog2
print(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)