潮流有货 2025-11-05 09:55 采纳率: 98.4%
浏览 0
已采纳

原神抽奖概率如何通过代码实现?

在模拟原神抽卡系统时,如何通过代码准确实现“保底机制”与“概率递增”的混合逻辑?常见问题是:当用户连续抽取未获得五星角色时,系统需逐步提升获取概率(如从0.6%线性递增至第90抽必出),但若简单使用独立随机数判断,容易导致保底机制失效或概率偏差。如何设计状态机与累积计数器,确保既符合官方公布的概率规则,又能正确触发90抽必得五星的保底?同时,在复刻角色池中还需区分UP角色与常驻角色的权重分配,这对随机算法的精度和可维护性提出了更高要求。
  • 写回答

1条回答 默认 最新

  • rememberzrr 2025-11-05 10:31
    关注

    模拟原神抽卡系统中的保底机制与概率递增混合逻辑实现

    1. 问题背景与核心挑战

    在模拟《原神》抽卡系统时,最核心的机制之一是“保底机制”与“概率递增”的结合。官方公布的规则如下:

    • 单次抽取五星角色的基础概率为0.6%。
    • 若连续未获得五星,则从第74抽开始,概率线性递增至第90抽必出。
    • 每90抽为一个保底周期,确保至少获得一个五星角色。
    • 在UP池中,五星角色分为“UP角色”和“常驻五星”,其获取权重不同(通常UP概率约50%,其余为常驻或武器)。

    直接使用独立随机数判断会导致两个严重问题:

    1. 保底失效:若仅靠概率计算,可能出现超过90抽仍未出五星的情况。
    2. 期望偏差:用户感知的“非酋”体验与数学期望不符,影响模拟真实性。

    2. 设计原则与状态建模

    为了准确还原机制,需引入状态机累积计数器,将抽卡过程划分为多个阶段:

    状态描述触发条件
    IDLE初始状态新抽卡周期开始
    PROB_INCREASE概率递增区间(74~89抽)累计抽取≥74且<90
    GUARANTEED强制保底状态累计抽取=90
    RESET重置计数器获得五星后

    该状态机确保逻辑可追踪、可测试,并支持未来扩展(如四星保底)。

    3. 核心算法设计与代码实现

    以下为Python伪代码实现,展示关键逻辑结构:

    
    class GachaSimulator:
        def __init__(self):
            self.pity_count = 0          # 当前五星保底计数
            self.up_rate_up = 0.5        # UP角色在五星中的占比
            self.base_5star_rate = 0.006 # 基础五星概率
    
        def get_5star_probability(self):
            if self.pity_count < 74:
                return self.base_5star_rate
            elif self.pity_count < 90:
                increment = (self.pity_count - 73) * 0.06 / 6  # 每抽增加6%
                return min(1.0, self.base_5star_rate + increment)
            else:
                return 1.0  # 必出
    
        def draw_single(self):
            self.pity_count += 1
    
            # 判断是否获得五星
            p_5star = self.get_5star_probability()
            if random.random() < p_5star or self.pity_count == 90:
                is_up = random.random() < self.up_rate_up
                result_type = "UP_5STAR" if is_up else "PERMANENT_5STAR"
                self.pity_count = 0  # 重置保底
                return result_type
    
            return "NON_5STAR"
    

    4. 复刻池角色权重分配策略

    在复刻角色池中,需区分UP角色与常驻五星的分配逻辑。常见配置如下表:

    五星类型总五星中占比说明
    UP角色A50%本期主推角色
    UP角色B(复刻)25%若双UP则存在
    常驻五星角色25%如钟离、雷电将军等

    实现时应在判定获得五星后,再次进行加权随机选择:

    
    def choose_5star_type(self):
        weights = [0.5, 0.25, 0.25]  # 示例权重
        choices = ["UP_A", "UP_B", "PERMANENT"]
        return random.choices(choices, weights=weights)[0]
    

    5. 状态流转流程图(Mermaid)

    graph TD A[开始抽卡] --> B{pity_count < 74?} B -- 是 --> C[按基础概率判定] B -- 否 --> D{pity_count < 90?} D -- 是 --> E[按递增概率判定] D -- 否 --> F[强制出五星] C --> G{是否出五星?} E --> G G -- 是 --> H[重置pity_count=0] G -- 否 --> I[pity_count++] I --> B H --> J[返回结果] F --> H

    6. 测试验证与统计校准

    为确保模拟精度,应进行大规模抽样测试。例如运行10万次单抽,统计实际五星出率:

    抽卡次数理论出率实测出率偏差
    10.60%0.61%+0.01%
    746.60%6.58%-0.02%
    8012.60%12.55%-0.05%
    8518.60%18.62%+0.02%
    90100%100%0%
    平均保底抽数~75.875.76-0.04
    UP角色占比50%49.8%-0.2%
    四星平均间隔10抽9.98抽-0.02
    双UP池UP总占比75%74.9%-0.1%
    常驻五星占比25%25.1%+0.1%

    通过蒙特卡洛模拟可验证系统符合官方公布的数据分布。

    7. 可维护性与扩展建议

    为提升系统的可维护性,建议采用配置化方式管理概率参数:

    
    {
      "gacha_config": {
        "base_5star_rate": 0.006,
        "soft_pity_start": 74,
        "hard_pity_limit": 90,
        "up_weight_in_5star": 0.5,
        "permanent_weight": 0.25,
        "weapon_pool_ratio": 0.75
      },
      "pools": {
        "character_event": {
          "up_chars": ["Naofumi", "Raiden"],
          "is_duplicate": false
        }
      }
    }
    

    结合依赖注入与工厂模式,可轻松支持多类型卡池(武器池、常驻池、新手池)的切换与热更新。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

问题事件

  • 已采纳回答 11月6日
  • 创建了问题 11月5日