什么是“随机”?教你区分“伪随机”和“真随机”
这是一个嘲笑不懂“概率”的人的笑话,却道出了“真随机”和“伪随机”的区别。
4月底,我写了一篇文章《玩游戏靠技术还是靠运气?,其中提到了“伪随机”的概念。当时限于篇幅,没有详细解释“伪随机”的概念。不久前,因为国际邀请赛而备受关注的Dota2最新更新中,有这样的更新:“失败的负面效果和下坡攻击的失败效果现在由伪随机触发。”
那么什么是“伪随机”呢?而“伪随机”对应的“真随机”是什么概念?
伪随机数发生器(PRNG)是一个计算机术语——当然也可以叫“伪随机数算法”,只是为了与游戏中的“伪随机数”相区别,本文称之为“伪随机数算法”。
众所周知,计算机程序是由无数个“0”和“1”状态组成的。如果一个状态不是“0”,那一定是“1”,相当黑白分明。
所以,在一个计算机程序中,没有“不确定”的数字,只有确定的“1”和“0”。基于这一特性,计算机无法产生“真实的(不确定的)随机数”。
那么当我需要在电脑中生成或者使用随机数的时候应该怎么做呢?通常是用计算机抓取一些数值,然后将这些数值输入到一个复杂的算法中(常用的算法有同余法和梅森旋转算法,有兴趣的读者可以自行查询,这里就不说了),通过一系列运算得到一个数,也就是俗称的伪随机数。
只要初始输入值(初始值)不变,输出值就会是同一个值,证明这个数不是随机的,只是看起来随机而已。
换句话说,只要这个随机数是用确定性算法生成的,就是伪随机数。
所以下次你和朋友聊真随机数和伪随机数的时候,如果有人打断你:“计算机只能生成伪随机数,所以根本没有什么真随机”,那你就可以说他是“云玩家”。
我们通常所说的真随机也叫“真随机分布”,就是我们常说的一般意义上的“随机”。
在真随机中,每个事件都是相互独立的,服从真随机分布,不被其他事件改变。比如某游戏为了吸引用户,有这样一个随机抽卡系统:每抽一张牌,有1%的概率抽到了SSR牌,服从真随机分布。
让我们回到开头说的那个笑话:这个笑话的不合理性我们一眼就能看出来。但是在抽牌游戏中,我们的大脑突然失去了理智。相当一部分玩家认为:我就算抽100次也总能抽到这张牌!
实际上,1% SSR卡在100次后抽不到的概率是(1-0.01)100 = 36.6%,甚至略超过1/3。还有4.9%的几率连续抽奖次数升至300。
换句话说,假设10000玩家连续抽100次,大概有3660个玩家抽不到这个SSR;10000玩家连续抽了300次,还有490个左右的玩家抽不到这个SSR——这可以说是对玩家游戏体验的毁灭性打击。
虽然纯随机在数学上是无罪的,在代码中更是清晰明了,但是玩家如果抽不到牌也不会回想初高中的数学课本,而是先怀疑概率是否被策划和操作篡改过,背后是否有肮脏的PY交易...
当然不仅仅是在抽卡系统。在一些竞争激烈的游戏中(比如War3和dota 2——英雄联盟几乎已经完全去掉了随机系统,除了这一款),连续几次的“运气”极大地影响了游戏的竞争力和观赏性。
比如Dota中最著名的概率英雄无脸虚空,拥有“回到过去”的技能:无脸虚空有25%的几率完全避免一次伤害。受War3引擎限制,该技能使用真随机概率。在一种极端的情况下(通常在精彩集锦中看到),无脸虚空可以保持低血量并忍受多重伤害而不死亡,最终杀死对手。这个给敌人带来糟糕游戏体验的系统也因此进入了设计者的“补救范围”。
为了避免游戏体验不佳造成的玩家数量损失,设计师提出了“伪随机”的概念:在不确定的随机事件中,通过一系列算法将随机事件均匀分布在多个事件中,尽可能减少或消除极端情况的发生,提高玩家的游戏体验。
在设计者的努力下,“伪随机”应运而生,这里的伪随机的含义不同于上面的伪随机数算法(PRNG)。
“伪随机”的制作方法有很多种,“伪随机分布”(简称PRD)在War3、Dota2等游戏中被广泛使用。
以Dota2中最强大的暴击技能为例:幻影刺客有15%的几率造成200%/325%/450%的暴击伤害。在PRD机制下,并不是幻影刺客攻击的每一刀其实都有15%的暴击率。
根据PRD机制的公式P(N)=N*C,15%概率的C值为3.22%,即幻影刺客第一次攻击的暴击概率为3.22%;如果第一刀不暴击,第二刀暴击率增加到2倍,即6.44%;如果还是没有暴击,就增加到9.66%的3倍,以此类推。
如果继续计算,第32刀暴击概率会达到100%,最有可能暴击数是第6刀,平均触发数是6.67刀等等。
同样,连续触发暴击时,下一刀的暴击几率也会降低。RPD机制降低了竞技游戏中连续触发或不触发技能的概率,避免了运气成分对战斗结果的过度干扰,极大地提升了玩家的游戏体验,但并不影响这些随机事件的正反馈:TI6决赛中的“打我五次,晕我三次”,却让全世界的人集体沸腾了!
除了RPD分布的伪随机,还有两种常见的伪随机:洗牌算法和组合随机。
洗牌算法最常见的用法是各大音乐播放器中的“随机播放”。随机播放时,如果采用真随机,一首歌根本不播放,或者同一首歌连续播放几次(有兴趣的读者可以计算一下这些概率)。为了解决这个问题,播放器采用的解决方案是洗牌算法:将一个包含所有歌曲的数组像洗牌一样进行洗牌,然后依次播放无序的数组。
至于组合随机,这是各种游戏中广泛采用的做法:在抽奖中做出两个或两个以上的判断,一个不是随机的,其余的都是真随机。比如第x次抽卡肯定会拿到SSR,但是SSR抽哪张卡是随机的——这就是广大手游中的“低保”制度。
在一堆数据中区分“真随机”和“伪随机”似乎不是那么容易。然后,我再介绍两个例子,帮助大家更好地理解什么是“真随机”和“伪随机”:
多么随机:有一天,小明在班上举行了一次抽奖。这个班有40个学生,所以为了公平起见,保证每个学生有1/40的中奖机会,老师准备了40个一模一样的纸箱,每个纸箱装40注,1注为中奖注。这样每个学生都有1/40的中奖机会,但是每个学生是否中奖不受其他学生的影响。在极端情况下,这个班有40名学生可能获奖。这真的是随机的。
伪随机:小明班级举行抽奖。为了公平起见,老师准备了1个纸箱,里面有40张纸,只有1张纸是中奖笔记。这样,每个学生都有1/40的获奖机会——但显然,这个班只有一个学生能获奖。一个学生中奖后,其余所有学生的中奖几率将降为零。这是伪随机的。