文/游戏陀螺 月夜猫

      随机性的设定为中国游戏带来很大推动,自《征途》出了开箱子玩法之后,无论是动作游戏,还是卡牌游戏,大部分都有抽卡或者扭蛋之类的设定,随机性这个设定在最近大热的《阴阳师》中被无限放大,因为这是一款没有保底的扭蛋方式,朋友圈盛传着“玄不救非,氪不改命!”来宣扬这个随机性究竟多难抽到自己心仪的SSR。

      玄不救非,氪不改命的意思是“玄学不能拯救非洲人,氪金不能改变命运”。此句话出自各大手游,特别是卡牌养成类游戏。而如今也应用在大部分网络游戏中。整句话带有嘲讽的意思,暗讽此人"脸黑”,“人品不好”。其实国内有大部分玩家有花钱的冲动,希望在游戏氪金来获得优待或是角色的能力或增加资源来增加获得稀有装备、物品的可能性。

      然而相比一般游戏有钱就能变强,舰C、阴阳师等一些游戏充了钱也是非洲人。就像最近经常看到有一些玩家吐槽,玩了一个多月《阴阳师》。氪金无数依旧无法抽到SSR。不过一般来说这类涉及到抽卡系统的基本都算是核心玩法和付费点,也可能就是快速提升游戏玩家实力的玩法。当然纯靠氪金的游戏是我们最熟悉的套路。而在《阴阳师》现象级产品的带动下,或许有一些团队也在尝试“氪不改命”的做法。对于普通玩家来说,也是一种公平性的体现,但这是建立在这里特定用户特性的基础上,并结合其它游戏元素刺激大R消费,直到抽到为止,满星为止。商业化的产品一定会追求商业收益。

      今天,游戏陀螺从另一个角度谈谈”玄不救非,氪不改命!”以下是几个简单下例子说“随机”抽取这件事。

      其实玄可救非,氪可改命!

      从编程角度来说,这个世界上是没有真“随机”这个概念的,通过计算的一切都有规律可言,真正意义上的随机数或随机事件,在某次产生过程中是按照实验过程中表现的分布概率随机产生的,其结果是不可预测的,是不可见的。而计算机中的随机函数是按照一定算法模拟产生的,其结果是确定的,是可见的。所以用计算机随机函数所产生的“随机数”,并不随机,而是伪随机。

      程序中的“随机”是什么?

      因为各种编程语言不同,所以,每个语种都有自己的独特随机算法,但是基本都会基于“种子”这个名词 。以前的程序员可能还会直接自己去写这段种子代码,而现在的程序员应该已经100%的调用某“种子函数”,然后在种子函数后添加自己的算法。

      一般而言,游戏中的随机,都是采用一个真随机数(种子)作为初始条件,然后用一定的算法不停的迭代产生随机数,现在一般都采用线性取余这种方式(因为简单)。

      用常见的C语言来解释,比如默认一个“种子”,这个种子可以是任何字母或者数字,但是如果种子不变,那么产生的随机数序列也不会变,常见的是调用“系统时间”当种子。

      扭蛋或者卡牌的随机抽取?游戏中随机抽奖的逻辑在这里

      用 srand(time(0)); 设种子,就会因时间变化,得到不同的种子,那么随机数序列就会变化。

      time(0) 是当前时间,(精度可能是毫秒)。只要两次跑程序启动时间差别 超过1毫秒,两个序列就不同了(随机),如果怕有卡随机规律,我们可以把这个取值范围加大,不过1毫秒做同样的两次操作,一般情况下,人类几乎无法实现。

      大部分游戏中最常见的也就是“时间种子”,90%的游戏中都采用这种“种子”作为随机算法的源头,简单直白的描述,就是采用系统本身的时间调用,这个时间可以精确到秒的后面N位,而常见的都是取小数点后面的随便两位数,然后通过一个确定好的规则算法来截取,比如下图:

      上图是一个简单的图解过程,正常上面的系统时间会有一个固定的函数转换,比如2-3位得出的是“A”,然后写好取值之后,全部都是用这个A在计算,比如上图的31,进入到对应的S区域,而S区域又同时拥有几十种甚至上百种可抽取的扭蛋结果,会额外增加一套算法,最后从中得到对应的编码,而这个编码就是实际上抽取到的S卡牌或者物品。(注:为了方便用户阅读,没有写入详细公式与求余等算法,而取余算法的目的是为了限制这个随机出来的数字值的大小,比如随机数字非常大,取“%1000”是为了生成的随机数不超过1000这个数字。)

      大部分游戏可能在进入第一次的品质区取值应该是最低品质的库取值范围最多,而最高品质的库,取值范围最小。有个别的游戏我们怀疑到SSS级别甚至是1,或者有部分游戏通过活动开启这个数字,平时的会把这个取值范围关闭,或者如果随机到这个数字在跳过去继续在次计算一次系统时间,这种取值最常见于卡牌游戏。(为了避免大量重复抽到某些极品,计算公式上可能还会用到异或算法,保证两次随机数不一样。)

      十连抽必出某某又是什么原理?不是十进制,而是10换1

      而所谓的十连抽必出“某某”,我们可以看成是一个程序计数器,这个计数器的模式是达到某个预设的数字后,自动跳转到另一个程序,通过另一种算法实现。直白一点的描述就是让程序自动计数,到达10次就调用另一套牌库,直接进入S区,然后在S区随机抽出某张牌,之后程序重置,反回之前的步骤,重复计数器为0的计数过程。(常见的十连抽都是这个原理,可以理解为满十次就换了一个物品库)

      几率性的百分比怎么计算?

      游戏中的随机概率性又是怎么实现的呢?比如攻击的时候有20%的几率出现暴击,这种情况一样多采用系统“时钟函数”实现,把暴击这个库临时创建(0-28为暴击,余下不暴击),然后依然沿用上面的算法。

      但是也有部分游戏采取另一种方式,这种方式是不调用时间函数,而是采用算法叠加,很少见,但是还是科普一下。

      系统中任何的表现,几乎都采用数字调用,而几率这种东西还有另一种表现方法。就是按数字算,这种常见于战斗中的算法,比如100次攻击中出现5次暴击,加上这20%就变成了10次攻击之中出现6次暴击。

      这个算法在最早期的单机游戏中非常的常见,而近来几年由于系统时钟可以提供更好的解决方案,几乎没有使用的了,因为游戏追求爽快感的同时,这种计算方式永远不会有100%暴击,还有一点,这种算法非常容易通过外挂等手段锁死暴击100%。这种类型比较典型的是像DNF之类的,即使某装备神器掉落率加300%,也仅仅是在原有的基础上多几个百分比,而不会每次都真的掉落神器。

      其实是有真随机数的 无限的才是最强大,但不可控的我们不要

      其实是有真随机数这一说法的,这个需要通过部分硬件来实现,比如采集物理噪音、宇宙射线、量子衰变等现实生活中真正随机的物理参数来产生真正的随机数。当然也有通过采集用户的点击位置或者输入方式等等不可预测的方式转换随机方式,或者用预读与加载等数据长度来作为随机种子,但是,这对于现在的手游用户而言,会使得系统增加太大的负担,导致游戏并不稳定,并且不可控,所以游戏中几乎不采用。

      现阶段游戏中其余基本都是采用标准库中自带的线性同余函数,其实这种随机就已经够用了,对系统算法压力会小一些,循环次数没有那么大。但有时候数值策划或者程序员那颗不想随便妥协的心会萌发出更多有意思的算法,这些算法才是最难琢磨的。

      严格来说无论什么样的随机数值设定,其实归根结底都是有规律可循的,只不过很多明明知道有规律的事,用户却无法琢磨,给个小建议,下次抽扭蛋,不妨换个时间试试。

      最近《阴阳师》中的抽卡概率在变化,SSR 的几率大增。

      (注:本文公式皆是简略版,仅原理上类似,如有不对欢迎指正)

如转载涉及版权等问题,请作者与我司联系,我司将在第一时间删除或支付稿酬。