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
Posted by: 马牧南山 | (32) November 19, 2020 05:43 PM
Posted by: colin | (31) April 27, 2020 11:23 AM
Posted by: Xagorz | (30) August 6, 2019 07:22 PM
Posted by: kk | (29) January 22, 2019 05:15 PM
Posted by: kk | (28) January 22, 2019 05:13 PM
Posted by: 韩毛毛 | (27) October 10, 2018 10:46 PM
Posted by: aka | (26) July 23, 2018 05:38 PM
Posted by: 阴阳师非洲大酋长 | (25) June 28, 2018 10:33 AM
Posted by: yolk | (24) March 8, 2018 09:02 PM
Posted by: Cloud | (23) February 26, 2018 08:34 PM
Posted by: 蝈蝈 | (22) February 26, 2018 08:11 PM
Posted by: yige819 | (21) December 21, 2017 05:55 AM
Posted by: 阳光宅男 | (20) August 13, 2017 04:03 PM
Posted by: lional1987 | (19) August 3, 2017 05:23 PM
Posted by: 味辣鸡 | (18) March 16, 2017 05:44 PM
Posted by: 味辣鸡 | (17) March 16, 2017 05:03 PM
Posted by: 陈冠希 | (16) March 15, 2017 11:24 AM
Posted by: pengdu | (15) February 18, 2017 02:23 PM
Posted by: pengdu | (14) February 18, 2017 01:50 PM
Posted by: startwing | (13) February 17, 2017 09:37 AM
Posted by: laixintao | (12) February 4, 2017 09:02 AM
Posted by: zhishu | (11) January 21, 2017 12:21 AM
Posted by: tuan | (10) January 17, 2017 06:29 PM
Posted by: hawk | (9) January 17, 2017 03:22 PM
Posted by: runesnag | (8) January 17, 2017 02:34 PM
Posted by: Cloud | (7) January 17, 2017 12:15 PM
Posted by: cmingjian | (6) January 17, 2017 11:56 AM
Posted by: 吃小朋友 | (5) January 17, 2017 10:38 AM
Posted by: Cloud | (4) January 17, 2017 10:32 AM
Posted by: tuan | (3) January 17, 2017 05:34 AM
Posted by: tuan | (2) January 17, 2017 01:15 AM
Posted by: arnan | (1) January 17, 2017 12:50 AM