本帖最后由 ofz 于 2015-1-16 21:30 编辑
hihihi,晚上好。
据我所知随机数生成器和初始化种子在多数语言里都是标准的配置(如 c 里面的 srand,java 里面的 Random(seed),与其自己费脑筋去实现一个 RNG,如果没有特殊需求的话还是用这些经过精心编写并广泛验证的东西比较好呢。但如果用的是 javascript 这种功能上残缺的(只有随机数生成器而不能设置种子),或者是在 shader 这样底层的环境下,自己写随机数生成器似乎就是必须的了
嘛,伪随机数的算法很多的,我也没有特地去了解过。参考这边的帖子,随便贴几个方案好了(以下都是 javascript
http://stackoverflow.com/questions/521295/javascript-random-seeds
1. 最简单偷懒的办法:直接利用正弦函数的分布
- var seed = 1;
- function random() {
- var x = Math.sin(seed++) * 10000;
- return x - Math.floor(x);
- }
复制代码 应该不要过多解释吧(在 shader 里面会看到类似的代码)。这个方法足够简单,速度也还可以。但缺点同样明显:因为正弦函数本身不均匀的特性,会有更高的概率出现在 0 或者 1 附近(看 http://jsfiddle.net/bhrLT/17/
2. 稍微复杂但可靠一点的
- var m_w = 123456789; // seed 1
- var m_z = 987654321; // seed 2
- var mask = 0xffffffff;
- // Takes any integer
- function seed(i) {
- m_w = i;
- }
- // Returns number between 0 (inclusive) and 1.0 (exclusive),
- // just like Math.random().
- function random()
- {
- m_z = (36969 * (m_z & 65535) + (m_z >> 16)) & mask;
- m_w = (18000 * (m_w & 65535) + (m_w >> 16)) & mask;
- var result = ((m_z << 16) + m_w) & mask;
- result /= 4294967296;
- return result + 0.5;
- }
复制代码 算法的细节我不懂,看 http://en.wikipedia.org/wiki/Multiply-with-carry
3. 再掺和进去一些 Magic Number
- // the initial seed
- Math.seed = 6;
-
- // in order to work 'Math.seed' must NOT be undefined,
- // so in any case, you HAVE to provide a Math.seed
- Math.seededRandom = function(max, min) {
- max = max || 1;
- min = min || 0;
-
- Math.seed = (Math.seed * 9301 + 49297) % 233280;
- var rnd = Math.seed / 233280;
-
- return min + rnd * (max - min);
- }
复制代码 说到算法里面的 Magic Number(就是那些不知道怎么来的奇怪数字),印象最深的还是卡马克大神的浮点数开方算法呢(那是我第一次在代码注释里面看见 WTF...
咦,你说你是做游戏的,但是你不认识卡马克大神?赶紧去看 doom启示录 吧,他一定会成为你的偶像的!
4. 最安全稳妥的办法:按照某种成熟的算法自己实现一个 PRNG
比如这边就是一个 javascript 上面用 RC4 算法写的 PRNG https://github.com/davidbau/seedrandom
技术细节参考 http://davidbau.com/archives/201 ... d_quintillions.html
稍微提一下,可能有人觉得奇怪,随机数只是用来增加游戏的不可预测性的和乐趣的,还跟安全性有关吗?抛开利用随机数来生成密钥这样的使用方式,拿一个俄罗斯方块游戏来说,随机数将决定下一次会出现什么类型的方块。如果你的随机数算法不够健壮,那么玩家可以通过之前出现的方块的顺序推测出你使用的算法和种子,由于伪随机数的本质,游戏接下来会出现的什么方块他就都可以预测出来了!最差的情况是某人可以根据这个写一个自动玩游戏的程序。唔...就这个例子来说,似乎危害不够大呢...也许应该拿纸牌之类的游戏举例子比较好,但是我不会玩牌(摊手
最后贴一句来自我们的 “计算机之父” 冯-诺依曼 的意(bi)味(ge)深(hen)长(gao)的话
"Anyone who uses arithmetic methods to produce random numbers is in a state of sin."
-- John von Neumann
|