随机数应用:伪随机机制

一、总论
1.伪随机机制的意义
1.1 什么是伪随机机制

日常生活中大家都喜欢玩单机或者网络游戏,而在这些游戏中常常会存在随机,比如暴击率20%或者被动击晕15%等等,而在这些随机事件中,我们往往被告知这些随机事件也能分成两类:一类是固定的概率,常被称为“真随机”,另一类是根据游戏行为有变化的概率,则叫做“伪随机”。我们都知道计算机只能产生伪随机数,那么这里的“真随机”和“伪随机”也不是我们通常对于计算机生成随机数的随机性质的定义,而是关于这个可见概率的具体实施方法。

1.2 为什么要使用伪随机机制

所谓的“真随机”在足够大的样本下,其中某一段的连续样本会距离整体期望产生较大的偏差,简单地说,就是“脸黑,怎么一直不暴击”或者“怎么脸那么好,一直在爆击”。而“伪随机”则在具体的游戏进程中对概率进行了及时的修正,以图实现足够稳定的样本子序列。举个简单的例子的话,就是当你打不出爆击时会增加下一次的概率,而你连续打出爆击时则会降低概率,虽然这对于某些运气好的玩家来说可能是一个噩耗,但是总体上来说,这挽救了某些运气实在太糟糕的朋友。

  1. 一个合理的伪随机机制的数据
    2.1 以一个被动击晕技能为模版

假设这个技能来自某款知名ARPG游戏,并且这个技能在某个前版本里被修正成了伪随机机制
被动击晕:概率25%
显然这个数据的大小是和我们玩的各类游戏中的被动都十分接近的,所以这个样本有其代表性

2.2 伪随机机制的实现数据

首先需要感谢前辈们为我们分析出了WAR3这款经典的RTS游戏内的伪随机实现过程,我们可直接套用这个关系来实现我们的伪随机机制。

P是游戏中显示的概率,c是实际操作概率,maxN是第N次连续不触发后必定触发的临界,Pcount为大样本测试下的实际概率
而具体实现流程则是
1.第一次攻击,概率为C,如果暴击返回1,未爆击进入2
2.第二次攻击,概率为2C,如果暴击返回1,未爆击进入3
……
N.第N次攻击,必定爆击,返回1
那么我们的代码也会依照着这样一个明确的流程来实现。

二、实现

//伪随机实现过程
#include<iostream>
#include<cstdlib>
#include<cstring>
using namespace std;
#define P 200   //P和C均扩大若干倍以方便计算
#define C 84.75 //
#define maxN 11 //参照表格
#define Num 100 //实际测试组数
int main()
{
    bool a[1001];
    double cUsing=C;
    int p,count=0;
    int i,j;
    srand(time(NULL));
    for(i=1;i<=Num;i++){
        memset(a,false,sizeof(a));
        for(j=0;j<=(int)cUsing;j++){
            a[j]=true;
        }
        p=(int)1000*rand()/RAND_MAX;
        //根据数组的值判断是否生效
        if(a[p]){
            cout<<cUsing<<" Y"<<endl;
            count++;
            cUsing=C;
        }
        else{
            cout<<"N"<<endl;
            cUsing+=C;
        }
    }
    cout<<1.0*count/Num<<endl;
    return 0;
}
Num 实际样本概率(理论值0.25) 误差[(理论-实际)/理论] 
100  0.235 -0.06 
1000  0.255 0.02 
100000  0.24989 0.00044 
100000  0.25048 0.00192

可以料想到随着样本的足够大,我们的确可以实现较为稳定的输出结果:25%的暴击概率

三、总结
随着网络游戏的不断发展,概率触发这个增进游戏不确定度的机制在游戏中愈发多的被使用,如炉石传说中的食人魔一族、DOTA2中各类击晕和爆击,甚至是整个RPG游戏族内的装备爆率,都要利用到概率这一利器,而其中有一些是固定概率的“真随机”,而另一部分则是不定概率“伪随机”,这些各有特色的机制让我们的游戏过程更为随机,让我们的游戏结果更为的出乎意料,也让我们获得了更多快乐。
而这个应用则让我们实际操作了一次伪随机机制的运行过程,让我们对游戏背后的运行原理加深了理解,希望能够帮助到未来有志于从事游戏开发的朋友。

分享-Sharing

发表评论

电子邮件地址不会被公开。