综合python案例,哪队能笑到最后?

wen python案例 1

本文目录导读:

综合python案例,哪队能笑到最后?

  1. 运行结果解析(预测)
  2. 如何调整?

这是一个非常经典且有趣的Python综合案例,既然你问“哪队能笑到最后”,我猜你可能是在做一个模拟比赛策略博弈的项目。

为了满足“综合”的要求(涵盖面向对象、数据结构、随机性、算法),我为你设计了一个 “NPC大乱斗” 模拟器。

场景设定: 有三支队伍(战士队、法师队、刺客队),每队有3名角色,他们进行循环赛(两两对决),最终根据积分(胜3平1负0)和净胜分决出总冠军。

下面是一段完整、可直接运行的Python代码,它会模拟整个赛程并告诉你哪支队伍笑到了最后

import random
import itertools
# ---------- 第一部分:构建角色基类(面向对象) ----------
class Hero:
    def __init__(self, name, hp, attack, defense, speed, crit_rate=0.2):
        self.name = name
        self.max_hp = hp
        self.hp = hp
        self.attack = attack
        self.defense = defense
        self.speed = speed
        self.crit_rate = crit_rate  # 暴击率
        self.is_alive = True
    def take_damage(self, damage):
        # 防御减伤
        actual_damage = max(1, damage - self.defense)
        self.hp -= actual_damage
        if self.hp <= 0:
            self.hp = 0
            self.is_alive = False
        return actual_damage
    def attack_target(self, target):
        # 基础攻击计算暴击
        if random.random() < self.crit_rate:
            damage = int(self.attack * 1.5)  # 暴击150%
        else:
            damage = self.attack
        final_dmg = target.take_damage(damage)
        return f"{self.name} 攻击 {target.name},造成 {final_dmg} 点伤害"
    def reset(self):
        self.hp = self.max_hp
        self.is_alive = True
    def __str__(self):
        return f"{self.name}(HP:{self.hp}/{self.max_hp})"
# ---------- 第二部分:定义三个特殊队伍(继承与多态) ----------
class Warrior(Hero):  # 战士:高攻高防,技能是破甲
    def special_skill(self, target):
        # 无视防御的打击(相当于真实伤害)
        damage = int(self.attack * 0.8)
        real_dmg = target.take_damage(damage + target.defense)  # 无视防御
        return f" [战士技能]破甲斩!无视防御,造成 {real_dmg} 点伤害"
class Mage(Hero):  # 法师:脆皮高爆发,技能是群体火球(或双体)
    def special_skill(self, targets):
        # 随机选1-2个目标攻击(这里简化,选第一个和目标攻击力最高的)
        if len(targets) == 1:
            targets = targets * 2
        # 攻击所有存活目标(这里限制最多打2个)
        dmg_list = []
        for t in targets:
            if t.is_alive:
                dmg = int(self.attack * 1.2)
                final_dmg = t.take_damage(dmg)
                dmg_list.append(t.name + ":" + str(final_dmg))
        return f" [法师技能]烈焰风暴!对 {', '.join(dmg_list)} 造成伤害"
class Assassin(Hero):  # 刺客:极高速度与暴击,技能是连续攻击
    def special_skill(self, target):
        total = 0
        # 刺客攻击三次(每次50%攻击力)
        for _ in range(3):
            if target.is_alive:
                dmg = target.take_damage(int(self.attack * 0.5))
                total += dmg
        return f" [刺客技能]影刃连击!合计造成 {total} 点伤害"
# ---------- 第三部分:构建比赛逻辑(算法与数据处理) ----------
class Team:
    def __init__(self, name, heroes):
        self.name = name
        self.heroes = heroes  # 列表(三名英雄)
        self.wins = 0
        self.losses = 0
        self.points = 0
        self.score_diff = 0  # 净胜分
    def reset(self):
        for h in self.heroes:
            h.reset()
        # 全场总生命值作为比赛输出指标
        self.total_hp = sum(h.max_hp for h in self.heroes)
    def is_defeated(self):
        return all(not h.is_alive for h in self.heroes)
    def get_alive_heroes(self):
        return [h for h in self.heroes if h.is_alive]
    def __str__(self):
        return self.name
def battle_phase(team_a, team_b):
    """
    进行一个回合(两两对战直到一方全灭)
    返回 (胜者team, 败者team, 剩余血量比)
    """
    # 初始化双方reset
    team_a.reset()
    team_b.reset()
    # 打乱顺序,体现随机性(用列表存储所有存活角色)
    all_heroes_a = list(team_a.heroes)
    all_heroes_b = list(team_b.heroes)
    round_num = 0
    # 主循环:直到一方团灭
    while not team_a.is_defeated() and not team_b.is_defeated():
        round_num += 1
        # 行动顺序按照速度排序(所有存活角色混合)
        alive_a = team_a.get_alive_heroes()
        alive_b = team_b.get_alive_heroes()
        combatants = []
        # 为每个英雄分配一个队伍标签
        for h in alive_a:
            combatants.append((h, 'A'))
        for h in alive_b:
            combatants.append((h, 'B'))
        # 按速度排序(如果速度相同则随机先手)
        combatants.sort(key=lambda x: (x[0].speed, random.random()), reverse=True)
        # 逐个行动(每个英雄行动一次就算一轮回合结束)
        actions_log = []
        for hero, camp in combatants:
            if hero.is_alive:
                # 选择目标(随机敌方存活英雄)
                if camp == 'A':
                    enemies = team_b.get_alive_heroes()
                else:
                    enemies = team_a.get_alive_heroes()
                if not enemies:
                    break  # 没有敌人了退场
                target = random.choice(enemies)
                # 决定使用普通攻击还是技能(技能概率40%)
                if random.random() < 0.4:
                    # 法师技能可以多重目标
                    if isinstance(hero, Mage):
                        # 法师可能群体攻击(这里简化,攻击所有,但伤害衰减)
                        log = hero.special_skill([target] + [enemies[0] if len(enemies) > 1 and enemies[0] != target else target])
                        actions_log.append(log)
                    else:
                        # 其他职业对单体
                        log = hero.special_skill(target)
                        actions_log.append(log)
                else:
                    log = hero.attack_target(target)
                    actions_log.append(log)
                # 检查战斗结束条件
                if team_a.is_defeated() or team_b.is_defeated():
                    break
        # 防止死循环(如果双方都不掉血则强制结束——这里加个保险)
        if round_num > 100:
            # 比较血量百分比
            a_hp = sum(h.hp for h in team_a.heroes)
            b_hp = sum(h.hp for h in team_b.heroes)
            if a_hp >= b_hp:
                winner, loser = team_a, team_b
            else:
                winner, loser = team_b, team_a
            return winner, loser, actions_log
    # 正常结束
    if team_a.is_defeated():
        winner, loser = team_b, team_a
    else:
        winner, loser = team_a, team_b
    return winner, loser, actions_log
# ---------- 第四部分:主程序与统计(综合应用) ----------
def create_teams():
    # 创建三支队伍
    # 战士队 - 血厚攻高防高
    soldier1 = Warrior("盾战", 300, 80, 25, 50, 0.1)
    soldier2 = Warrior("狂战", 280, 100, 15, 60, 0.2)
    soldier3 = Warrior("枪兵", 250, 90, 20, 70, 0.15)
    team_war = Team("钢铁战士队", [soldier1, soldier2, soldier3])
    # 法师队 - 控制爆发
    mage1 = Mage("火法", 180, 130, 10, 70, 0.25)
    mage2 = Mage("冰法", 200, 120, 8, 65, 0.2)
    mage3 = Mage("雷法", 170, 150, 5, 80, 0.3)
    team_mage = Team("奥术议会队", [mage1, mage2, mage3])
    # 刺客队 - 脆皮极速
    assassin1 = Assassin("暗刃", 150, 100, 5, 95, 0.45)
    assassin2 = Assassin("影袭", 160, 90, 5, 100, 0.5)
    assassin3 = Assassin("夜行者", 140, 110, 5, 90, 0.4)
    team_assassin = Team("暗影猎手队", [assassin1, assassin2, assassin3])
    return [team_war, team_mage, team_assassin]
def simulate_tournament():
    teams = create_teams()
    print("="*60)
    print("               🏆 模拟大赛正式开始 🏆")
    print("="*60)
    for team in teams:
        print(f"  🎖 队伍: {team.name}  |  成员: {', '.join(h.name for h in team.heroes)}")
    print()
    # 循环赛:每两队打一场,三局两胜?这里简单一场定胜负,但为了公平每场打3次取积分
    team_names = [t.name for t in teams]
    matches = list(itertools.combinations(range(3), 2))
    # 每个对阵打一场(循环赛 3场)
    for match_idx, (i, j) in enumerate(matches):
        team_a = teams[i]
        team_b = teams[j]
        print(f"\n--- 对阵 {match_idx+1}: {team_a.name}  VS  {team_b.name} ---")
        # 这里每场进行3局,胜场多者得3分,平局则各1分(无平,实际不会平)
        # 我们改为单场,但是为了模拟更真实,多局取分
        points_a = 0
        points_b = 0
        for game in range(1, 4):  # 三局
            winner, loser, log = battle_phase(team_a, team_b)
            # 计算净胜(剩下的总血量比)
            a_hp = sum(h.hp for h in team_a.heroes)
            b_hp = sum(h.hp for h in team_b.heroes)
            diff = a_hp - b_hp  # 可能是负
            if winner is team_a:
                points_a += 1
                print(f"   第{game}局: {team_a.name} 胜 (剩余血量 {a_hp} vs {b_hp})")
            else:
                points_b += 1
                print(f"   第{game}局: {team_b.name} 胜 (剩余血量 {a_hp} vs {b_hp})")
            # 更新积分(总分)
            if points_a > points_b:
                leading = team_a
            elif points_b > points_a:
                leading = team_b
        # 结算分数(3局2胜)
        if points_a >= 2:
            team_a.points += 3
            print(f"  >>> 最终胜者: {team_a.name}")
        else:
            team_b.points += 3
            print(f"  >>> 最终胜者: {team_b.name}")
    print("\n" + "="*60)
    print("                          战绩统计")
    print("="*60)
    # 计算净胜分(用胜场差简单代替)
    # 为了好玩,这里看所有对局小分
    results = sorted(teams, key=lambda t: t.points, reverse=True)
    for rank, team in enumerate(results, 1):
        print(f"{rank}位 🥇  : {team.name}  |积分: {team.points}")
    champion = max(teams, key=lambda t: t.points)
    print("\n" + "*"*60)
    print(f"       🎉 最终的冠军是: {champion.name} 🎉")
    print("*"*60)
    # 冠军额外奖励
    for h in champion.heroes:
        print(f"         🏅 {h.name} 荣誉登场!")
# 运行模拟(因为随机性,结果会变化,想固定可加 random.seed(42))
if __name__ == "__main__":
    # random.seed(1)  # 取消注释固定随机种子看固定结果
    simulate_tournament()

运行结果解析(预测)

由于引入了随机性(暴击、技能触发、目标选择),每次运行结果可能不同,但从属性数据上看

  • 战士队:血厚、防高,容错率高。
  • 法师队:攻击力高,但非常脆,技能是AOE,但单体爆发可能不足。
  • 刺客队:速度极快(几乎总是先手),暴击率极高(50%左右),伤害非常恐怖,由于速度快,可能先秒杀敌方输出。

“哪队能笑到最后?” 答案通常在刺客队法师队之间(取决于刺客的暴击是否触发),如果刺客连续打出暴击,基本上三回合内能秒掉对方主力,而战士队更稳定,但输出可能略显不足,面对高爆发队伍时容易陷入困境。

你可以多次运行这个程序,看看统计上哪支队伍的赢面更大😊


如何调整?

  • 修改 Hero 的初始属性(HP/攻击/速度等)来调整队伍平衡。
  • 修改 battle_phase 中的技能触发概率(4)来让技能更容易释放。
  • 想固定比赛结果,在 __main__ 中调用 random.seed(某数字) 即可。

(小建议:如果想让真正的“综合”,可以加入文件读取(如英雄名单存CSV)、画图(matplotlib显示胜率),但核心逻辑已在这几百行里体现了。)

抱歉,评论功能暂时关闭!