« 豆豆的日常 | 返回首页 | 一个简单的 lua 对象回收再利用方案 »

10 连抽保底的概率模型

网游里有很多抽卡、开箱子之类的赌性玩法,在最开始,游戏设计者实现的时候,仅仅给这些抽取概率简单的设置了一个值。比如抽卡抽出橙卡的概率是 10% ,那么就是说,玩家每次抽一张卡,有 90% 的可能是白卡,10% 的可能是橙卡。

但大 R 玩家是大爷,需要小心伺候。如果感受不好,人跑了就亏大了。概率这个东西靠改进伪随机数发生器是解决不了体验问题的,大爷要是连抽 20 张都出不来橙卡,那是要怒删游戏的。

连抽 20 张 10% 概率橙卡一张都抽不到的机会多不?一张抽不中的概率是 0.9 ,20 张都抽不中的概率是 0.9 ^20 = 12.2% 。这可不算小数字啊。平均 8 个大 R 就会碰到一次,一下子赶跑了 1/8 的金主,这个责任小策划可担当不起。

所以、一般网游都会用各种规则来避免玩家出现连抽不中的尴尬。例如,我忘记是谁发明的 10 连抽规则:如果你购买一个大包连抽 10 次,我在规则上就保证里面一定至少有一张橙卡。实现它应该并不困难,按常规概率生成 10 张的卡包,如果里面没有橙卡,那么我加一张即可。

但如果我想把 10 抽保底的规则惠及日常抽卡的玩家该怎么做呢?

就是说,我希望任何玩家任何时候,接连抽了 10 张卡,我都想保证这 10 张卡里至少有一张橙卡。

首先,要说明的一点:如果你同时想保证橙卡掉落率是 10% ,也就是在极大范围内,比如系统投放了一万张卡片中,其中要有一千张橙卡。那么同时保证每 10 张卡里有至少一张橙卡的话,结果一定是完全不随机的,也就是必须每抽 9 张白卡,必出一张橙卡。

所以、如果即想要随机(出橙卡的概率稳定),又想有 10 张出一张的保底,那么橙卡投放量是一定超过 1/10 的。

我们之前的游戏用了个很粗暴的方案:记录玩家已经连续几次没有抽中,如果连续次数超过 9 ,就必给他一张橙卡。为什么我说这个方案粗暴,因为它其实破坏了抽卡的自然体验。虽然玩家的确更高兴了,但是概率却很不自然。不自然的方案(其实是生硬的打了个补丁)实现起来还容易出错,我们前段时间就因为实现 bug 多发放了很多稀有物品,这个 bug 就不展开说了。

下面来看看,为什么这么做不自然。

假设橙卡的掉率是 10% ,那么你在获得一张橙卡后,再抽下一张橙卡的概率就是 0.1 。下一张是白卡,再下一张是橙卡的概率是 0.9 * 0.1 ,下两张是白卡,第三张是橙卡的概率是 0.9^2 * 0.1 ……

后续有 10 张及 10 张以上的概率总共有多少呢?我算了一下,大约是 35% 左右。

我们把抽到两张橙卡之间会抽取到的白卡张数排成一个数列的话,这个数列的值的范围是 0 到正无穷。是的,非洲酋长可能永远抽不到橙卡。当然这只是理论值。

如果你读过大学,学的是理工科,没有逃课的话,就应该知道,这个数列是大致符合指数分布的。指数分布正是用来表示独立随机事件发生的时间间隔的。

当我们把这个数列中大于 9 的数字都强行改成 9 ,那么 9 的出现频率就陡然跳变,这是极不自然的。(分布不平滑)


从一致分布的随机数,转换为指数分布的随机数非常简单。如果你懒得自己推导,那么可以在爆栈网上找到公式

让我们回答前面的问题,如果我希望获得一个大约每 10 张卡里出一张橙卡的随机数列,除了每次 random 一个 [0,10) 的整数,判断证书是不是 0 以外,还有一个方法。那就是每次抽到一个橙卡后,都从一个指数分布的随机数列中取一个值出来,作为接下来会抽取到白卡的张数。按这个张数去发放白卡,等计数器减到 0 ,就发一张橙卡给玩家。这个白卡张数的数值范围是 [0, inf) 。

用 lua 实现的话,大概是这样的:

math.floor(math.log(1-math.random()) * (-rate)) 其中 rate = 10 。

好了,如果我们想加上 10 张保底,又想让间隔大致符合指数分布怎么办?简单:

function erand(rate)
    while true do
        local p = math.floor(math.log(1-math.random()) * (-rate))
        if p < rate then
            return p
        end
    end
end

让产生出来的数字小于 10 的时候重来一次就好了。如果你担心这里死循环(实际并不会),也可以加上循环上限:

function erand(rate)
    for i = 1, 100 do  -- 100 可以随便写
        local p = math.floor(math.log(1-math.random()) * (-rate))
        if p < rate then
            return p
        end
    end
    return rate-1
end

当然,一旦加上了 10 张保底,单张出橙卡的概率就大大增加了,增加到多少呢?大约是 21%。如果你希望保持 10% 左右的投放率,那么保底张数大约应该设置在 23 张左右。


ps. 今天在公司群里讨论这个问题时,雷先生提了这么一个问题,说是可以用来做数值策划的面试题:

已知橙卡的抽取率是 10% ,抽一次卡是 1 块钱;而 10 连抽的包可以帮你按同样概率连抽 10 次,但如果没有抽到橙卡的话,系统会补偿一张橙卡给你,换掉 10 张白卡中的一张。

假设白色一文不值,只有橙卡值钱。

那么请问:这个 10 连抽的包到底价值多少?

Comments

很尴尬。。算错了,然后想错了。。

随着抽卡的次数增多,玩家的收益其实是边际效益递减的。
抽1次卡 橙卡的期望值是0.1张
抽2次卡 橙卡的期望值是0.19张
抽3次卡 橙卡的期望值是0.282张

所以金钱并不和橙卡的数量直接挂钩,而是和出橙卡的概率直接挂钩,借用楼上的期望1.348 , 我们要找到的是
抽N次卡 橙卡的期望值是1.348 其中N的数值,而不能直接由一次抽卡的期望直接换算

原来概率p1 = 10%
保底概率p2 = 0.9^10 ≈ 35%
橙卡概率p = p1 + p2 = 45%
所求价值v = 10 * p = 4.5¥

前提:10%是真概率

十连抽的保底期望是抽到1.3486784401张橙卡。

10%的单抽概率抽到橙卡,单抽一次一块钱,推出橙卡价格是10块钱。

那样十连抽的价值就是13.5块,但是实际出售价格应该还是设置为10块吧。

如果要抽n次掉落1个装备的话,根据war3掉金币的算法是:
第一次掉落概率:k
第二次掉落概率:2k
第三次掉落概率:3k
……

算一下期望就是:
k * 1 + (1 - k) * 2k * 2 + (1 - k) * (1 - 2k) * 3k * 3 + ... = n

可以策划去配置这个n,然后程序二分k的数值把k算出来

以n = 10为例,k = 0.014746
抽第一次的概率是:1.4746%
第二次:2.9492%
第三次:4.4238%
第四次:5.8984%
第五次:7.373%
第六次:8.8476%
第七次:10.3222%
第八次:11.7968%
第九次:13.2714%
第十次:14.746%
结合实际应用来看,再加上一点特殊处理:
1,如果前九次不中,第十次必中
2,如果前面有中的,后面一定不中

以上适用于单次单次的抽,可以给用户一个较好的体验。如果是十连抽的话,可以有更简单的实现方式了。

我闻到了一丝坏味道。

1*0.1^1*0.9^9+
2*0.1^2*0.9^8+
3*0.1^3*0.9^7+
...
+9*0.1^9*0.9^1+
1*0.9^10

不知道对不对……

保底的几率是0.348左右,答案是1.348吧

我明白了,你这个相当于先模拟抽,超出23次不中的就扔掉。其实就相当于保底23次。
ps. 指数分布/泊松分布可以由二项分布推导出来,可以说它们描述的是二项分布的另一面(这里用泊松分布可能更符合你的要求,因为是离散的)
ps.. 最后那道题,是不是该换一种问法:一张橙卡价值几何

一个小结果,没有保底发放100张卡,有10张橙卡,有保底的就会大概是15张橙卡。
假设有100个人 每个人都一直抽到橙卡为止 会出现oranCard张橙卡 whiteCard张白卡 一共oranCard + whiteCard张卡:

橙卡:100
白卡:551.3215599
橙卡/(橙卡+白卡):0.15353399327876
没有保底的话 橙卡/(橙卡+白卡)=0.1

想确认下计算方法是不是我假设1000次抽取样本中,10连抽中白卡的概率为31.8%,可以理解为只要设了10连保底,那么就有31.8%的概率出橙卡,同时加上10%本身产出的概率,所以就有41.8%的概率产出橙卡。所以包的价值为0.418乘以橙卡单价。

@tuan

无论什么方法,都是觉得简单的在保底最后一次硬送过于粗暴,失去了赌性的乐趣。希望对此改进。

对于成功率递增的方法,我觉得最终的期望次数一定不是 N 。当然这没有问题。

我想如果有问题的话,应该在于先期的成功概率也被降低了。也就是连抽中的惊喜事件频率会比完全独立抽取(最终期望一致的情况下)发生的概率大大降低。

从体验角度说,我们不仅要避免大 R 当非洲酋长,也不能减少他们当欧皇的概率。

∵ 橙卡的概率是10%,抽一次卡是1块钱
∴ 橙卡值10块
且 抽10次且没有概率保护,价值就是10块
∵ 10次不中概率是pow(0.9,10)=0.35
∴ 0.35的概率额外获得一张橙卡
∴ 因为概率保护而获得的收益是0.35*10=3.5
∴ 10 连抽的包值13.5


这不是纯数学题么

@arnan

应该就是把前面各乘了 1.35 。严格说,间隔本不完全是指数分布,它是离散的。

招数值吗?这题我会做,我是失业数值……

以前做过类似的,比如装备强化,成功率逐渐升高。第i次的成功率为1/(2*N-i),则次数期望是N。相当于一个期望是N次的操作,保护2N-1次必定成功,简单明了。

想了想,加上这个while之后其实就不是指数分布了。
相当于也是把10之后的35%概率硬砍掉了,只是不是简单的加在9上,感觉是以一个指数分布叠加在另一个指数分布上,变成另一种更复杂的分布。

Post a comment

非这个主题相关的留言请到:留言本