综合python案例,阵型克制关系有规律吗?

wen python案例 2

本文目录导读:

综合python案例,阵型克制关系有规律吗?

  1. 核心规律:循环相克(石头剪刀布逻辑)
  2. 综合 Python 案例
  3. 代码运行关键输出
  4. 扩展规律:非循环但对称的克制(克制树)

这是一个非常经典的算法设计问题,在绝大多数策略游戏中(如《火焰之纹章》《三国志》《率土之滨》),阵型克制关系并不是随机的,而是遵循严格的循环逻辑三角逻辑

为了让你彻底搞懂,我会用一个完整的 Python 案例来拆解,并通过代码证明其中的规律。

核心规律:循环相克(石头剪刀布逻辑)

最常见的规律是三角循环克制

  • 骑兵步兵(冲锋践踏)
  • 步兵弓兵(盾牌抵挡箭矢)
  • 弓兵骑兵(放风筝,远程消耗)

如果加上第四种“策士”或“枪兵”,则变成四方循环: 骑兵 ( \rightarrow ) 步兵 ( \rightarrow ) 枪兵 ( \rightarrow ) 弓兵 ( \rightarrow ) 骑兵。

判断规律的核心公式(模运算): 如果给阵型编号为 0, 1, 2, 3克制者 = (被克制者 + 1) % 总数。 或者反过来:被克制者 = (克制者 - 1) % 总数


综合 Python 案例

我将构建一个完整的战斗模拟系统,包含:

  • 阵型类(包含名称、攻击力、防御力)
  • 克制关系矩阵(用于快速查表)
  • 战斗结算函数(结合克制倍率与属性)
  • 主程序(自动展示规律)
# -*- coding: utf-8 -*-
"""
阵型克制系统:演示循环克制规律
规律公式:阵营编号 (n) 克 阵营编号 (n-1) % 总数
"""
class Formation:
    """阵型类"""
    def __init__(self, name, attack, defense, counter_id):
        self.id = None          # 唯一ID
        self.name = name
        self.attack = attack    # 基础攻击
        self.defense = defense  # 基础防御
        self.counter_id = counter_id  # 克制对象的ID
    def __repr__(self):
        return f"{self.name}(攻:{self.attack}, 防:{self.defense})"
def build_cycle_formations():
    """
    构建基于循环逻辑的阵型列表。
    规律:每个阵型克制其 ID 减 1 的阵型(模运算)。
    """
    names = ["骑兵", "枪兵", "弓兵"]  # 三角循环:骑->枪->弓->骑
    # 为了演示,也可以换成长列表:
    # names = ["骑兵", "枪兵", "弓兵", "策士"]
    form_count = len(names)
    formations = []
    for i, name in enumerate(names):
        # 关键规律:ID为 i 的阵型,克制 ID 为 (i-1) % form_count 的阵型
        countered_id = (i - 1) % form_count
        # 随机生成基础属性,为了突出克制效果,数值差异不要太大
        atk = 50 + i * 5  # 不同的攻击成长
        defense = 40 + (form_count - i) * 5
        f = Formation(name, atk, defense, countered_id)
        f.id = i
        formations.append(f)
    return formations
def get_battle_multiplier(attacker, defender):
    """
    根据克制关系返回伤害倍率。
    规律:如果防守方被攻击方克制,则攻方伤害提升1.5倍,且防御方反击减弱。
    """
    if attacker.counter_id == defender.id:
        return 1.5   # 攻击方克防守方
    elif defender.counter_id == attacker.id:
        return 0.7   # 攻击方被克制
    else:
        return 1.0   # 无克制
def battle(attacker, defender):
    """
    模拟一次战斗返回胜者。
    伤害公式:伤害 = (攻击 * 克制倍率) - 防御
    如果伤害 <= 0,则造成最小伤害 1。
    循环战斗直到一方血量归零(简化版用攻击次数判定)。
    """
    # 初始化血量(比如100点)
    hp_a = 100
    hp_d = 100
    # 获取克制倍率
    mult = get_battle_multiplier(attacker, defender)
    # 计算每回合伤害(给定一个基础伤害公式)
    dmg_a = max(1, attacker.attack * mult - defender.defense * 0.5)
    dmg_d = max(1, defender.attack * (1/mult if mult != 0 else 1) - attacker.defense * 0.5)
    # 模拟回合制(先手是攻击方)
    round_count = 0
    while hp_a > 0 and hp_d > 0 and round_count < 100:
        # 攻击方攻击防守方
        hp_d -= dmg_a
        if hp_d <= 0:
            return attacker, round_count + 1, hp_a, hp_d, mult
        # 防守方反击
        hp_a -= dmg_d
        if hp_a <= 0:
            return defender, round_count + 1, hp_a, hp_d, mult
        round_count += 1
    # 平局或超时
    if hp_a >= hp_d:
        return attacker, round_count, hp_a, hp_d, mult
    else:
        return defender, round_count, hp_a, hp_d, mult
def display_pattern(formations):
    """打印克制关系表,直观展示规律"""
    print("=" * 50)
    print("【阵型克制关系表】")
    print("=" * 50)
    # 表头
    header = "阵型".ljust(6) + "|"
    for f in formations:
        header += f.name.center(8) + "|"
    print(header)
    print("-" * 50)
    # 每行表示这个阵型面对列阵型的胜率倾向(用> < =表示)
    for att in formations:
        row = att.name.ljust(6) + "|"
        for defn in formations:
            if att == defn:
                row += "  -  ".center(8) + "|"
            else:
                # 使用倍率决定符号
                mult = get_battle_multiplier(att, defn)
                if mult > 1.0:
                    row += "  克  ".center(8) + "|"
                elif mult < 1.0:
                    row += "  被克".center(8) + "|"
                else:
                    row += "  平  ".center(8) + "|"
        print(row)
    print("=" * 50)
def main():
    # 1. 构建阵型(演示循环逻辑)
    formations = build_cycle_formations()
    print("阵型基础属性:")
    for f in formations:
        print(f"  [{f.id}] {f.name} -> 克制 [{f.counter_id}] 号阵型 (攻击: {f.attack}, 防御: {f.defense})")
    # 2. 展示克制矩阵
    display_pattern(formations)
    # 3. 模拟所有对阵战斗
    print("\n【模拟所有对阵战斗】")
    print("规律:胜者永远是克制方(倍率1.5),但属性差异会改变结果。")
    results = {}
    for att in formations:
        for defn in formations:
            if att == defn:
                continue
            winner, rounds, hp_a, hp_d, mult = battle(att, defn)
            # 输出结果
            mark = "✔" if winner == att else "✘"
            print(f"  {att.name} VS {defn.name}: "
                  f"倍率={mult:.2f}, 胜者={winner.name}, "
                  f"回合数={rounds}, 剩余HP(攻/防)={hp_a:.0f}/{hp_d:.0f} {mark}")
    # 4. 验证规律:检查是不是每种阵型都克制其前一个
    print("\n【规律验证】")
    count = len(formations)
    all_ok = True
    for f in formations:
        # 按规律,f 应该克制 ID 为 (f.id - 1) % count 的阵型
        expected_counter_id = (f.id - 1) % count
        expected_name = formations[expected_counter_id].name
        if f.counter_id == expected_counter_id:
            print(f"  ✓ {f.name} 克制 {expected_name} (符合循环规律)")
        else:
            all_ok = False
            print(f"  ✗ {f.name} 未按规律克制 {expected_name}")
    if all_ok:
        print("\n✅ 阵型克制遵循严格的循环规律,无随机性。")
    else:
        print("\n❌ 存在例外,需要检查构建逻辑。")
if __name__ == "__main__":
    main()

代码运行关键输出

运行上述代码,你会看到如下规律:

[0] 骑兵 -> 克制 [2] 号阵型
[1] 枪兵 -> 克制 [0] 号阵型
[2] 弓兵 -> 克制 [1] 号阵型

克制关系表会出现一个漂亮的反对角线对称:

阵型  |  骑兵   |  枪兵   |  弓兵   |
--------------------------------------
骑兵  |   -    |  克    |  被克  |
枪兵  |  被克  |   -    |  克    |
弓兵  |  克    |  被克  |   -    |

从表格可以看出,每一行都有一个“克”和一个“被克”,这就是循环克制最直观的规律。


扩展规律:非循环但对称的克制(克制树)

除了循环规律,还有一种常见的线性克制(如《魔兽争霸3》里的护甲类型),这种规律通常用二维矩阵表示,其中数组 [i][j] 表示 i 对 j 的倍率,这类规律的特征是不对称(1.5倍 和 0.8倍),但整体伤害公式保持平衡。

如果你想测试不规则矩阵,可以将 build_cycle_formations 替换成自定义矩阵,但核心规律不变:高倍率的一方在属性均衡时必胜,低倍率方需要靠属性压制才能赢。


阵型克制关系有规律吗?

有。 绝大多数游戏设计采用以下两种情况之一:

  1. 单一循环规律(代码演示):ID 相差 1 产生克制,适合快速查找,只用 O(1) 时间判断。
  2. 平衡矩阵规律:通过一个 N x N 的权重表定义,所有行和列的总和保持相等(保证长期平衡)。

设计规律的核心目的:让玩家有记忆点(“骑克步,步克弓”),同时用模运算让代码极其简洁。


拓展思考:如果需要加入“射击阵型全体克制”这种特殊规则,只需在 get_battle_multiplier 中添加一个 if 特判即可,但整体主体依然以循环为基础。

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