尊重博主版权,该博客引用了以下博客内容:
详谈JS中实现种子随机数及作用
最近开发遇到了一个新功能,要求做到相同随机数。何为相同随机数,即每次使用相同的随机种子,产生相同的数字。在网上找了一下,只找到上面一篇博客,所以,这里为了让更多的人了解,博主决定自己写一篇博客,将原博客内容引用过来,让更多的人能够了解到这一内容。
其实,我们平时在开发过程中,经常会遇到随机数问题,例如,随机抽奖,微信飞机大战中,随机产生敌人位置等等。但实际上这些都是伪随机,用C语言开发的时候,使用random函数的时候,会发现,当我们直接调用这个方法的时候,每次运行都产生相同的随机数,所以,在调用这个方法的时候,都会用时间来做随机种子。当然,在JS中直接调用Math.random方法,就能直接产生随机数,这里不需要设置时间种子,JS底层已经为我们设置了随机种子,而且,每次是不一样的。既然是伪随机,那么,我们可以根据这个特性,每次设置相同的随机数,每次运行的时候,都产生相同的随机数。
Math.seed = 5;
Math.seededRandom = function(max, min) {
max = max || 1;
min = min || 0;
Math.seed = (Math.seed * 9301 + 49297) % 233280;
var rnd = Math.seed / 233280.0;
return min + rnd * (max - min);
for (var i= 0; i<10; i++) {
console.log(Math.seededRandom());
这里的Math.seed是自己定义的一个变量,Math.seededRandom也是自己定义的一个方法,如果不喜欢这种方式,也可以定义成其他的名字。下面,引用原博主的内容:
运行如上代码你会发现如果种子Math.seed不变,那么生成的随机数是不会变化的,哦了,如果引入这个函数,那么重现游戏场景可以实现了,虽然还需要做更多的细节处理,但机制上是能保证的,本文的重点不是实现一个这样的游戏。
本文的重点是:(Math.seed * 9301 + 49297) % 233280,为什么会是这三个值,而不是其它的到底这三个数字有什么神秘的
像Math.seededRandom这种伪随机数生成器叫做线性同余生成器(LCG, Linear Congruential Generator),几乎所有的运行库
提供的rand都是采用的LCG,形如:
I n+1=aI n+c(mod m)
生成的伪随机数序列最大周期m,范围在0到m-1之间。要达到这个最大周期,必须满足:
1.c与m互质
2.a - 1可以被m的所有质因数整除
3.如果m是4的倍数,a - 1也必须是4的倍数
以上三条被称为Hull-Dobell定理。作为一个伪随机数生成器,周期不够大是不好意思混的,所以这是要求之一。因此才有了:
a=9301, c = 49297, m = 233280这组参数,以上三条全部满足。
下面,我们来继续讨论刚刚上面的恢复敌人位置的问题。现在我们可以自己产生随机数了,而且,按照我们的要
求,可以每次都产生相同的随机数了。也就是说,我们可以每次随机敌人的位置了。
这时有人会问,为什么要每次产生相同的随机数呢?其实,这里有很大的用处,例如,我们在玩一个游戏的时候,随机产生了几个敌人的位置,这个时候,如果网络不好,重新连接进来,会发现,敌人的位置变了,此时,玩家看起来,就会发小屏幕上敌人位置发生了跳动,从玩家体验的角度来说,这是一种很差的体验。有人会说,为什么不在恢复现场的时候,直接将敌人的位置全部发送回来呢?下面,我来举一个简单的例子,来说明这个问题:
如果我们将敌人定义为1~10种类型,那么,正常情况下,如果我们为了在重新进入游戏的时候,继续上面的进度进行游戏,我们会将敌人类型和敌人位置都传回来,此时,我们传回来的数据格式,我用JSON简单来表示,大概应该是这种:
'enemyList':[{
'enemyType':1,
'x':33,
'y':25
'enemyType':2,
'x':45,
'y':67
'enemyType':3,
'x':84,
'y':12
那么,如果我们需要在服务器记录所有敌人的位置,如果用户量比较大,其实这数据量就挺大的了,而且,在重新进入游戏的时候,其实传回来的数据也是不少的。那下面,我们换一种思路,这次,我们每次计算玩家的位置都用随机数来计算,然后,当我们重新进入游戏的时候,服务器将相同的随机数种子发送到客户端,让服务器自己计算位置,同时将敌人的类型发回来,大概的数据格式如下:
'seed': 12345,
'enemyList':[1,2,3]
有没有觉得很精简,这样,不仅服务器储存的数据量大大减少,而且,服务器给客户端发包的时候,数据量也较少了好多,差不多是之前的1/3,这在开发中,真的好处很多的,玩家网络不好,中间网络断了,重新连接,可以恢复玩家当前的场景,网络不好,重连的时候,数据量减少了好多,如果用第一种办法,那重连了数据量反倒挺大的,这并不符合开发的要求啊,所以,在这里,随机数就真的起了大的作用。
以上就是产生相同随机数的方法,如果有什么描述不清楚地地方,欢迎大家留言交流!
尊重博主版权,该博客引用了以下博客内容:详谈JS中实现种子随机数及作用最近开发遇到了一个新功能,要求做到相同随机数。何为相同随机数,即每次使用相同的随机种子,产生相同的数字。在网上找了一下,只找到上面一篇博客,所以,这里为了让更多的人了解,博主决定自己写一篇博客,将原博客内容引用过来,让更多的人能够了解到这一内容。其实,我们平时在开发过程中,经常会遇到随机数问题,例如,随机抽奖,微信飞机大战中,随...
用于JavaScript的种子式伪随机数生成器。
它可以用作普通脚本或。
数字是使用单种形式的生成的。 尽管此方法对于大多数应用程序来说都是可行的,但在密码学上却不强。
jsrand支持在数组上保存和恢复生成器状态以及常见操作: (选择随机元素), (随机选择元素), (随机选择元素而不重复)和 。
choice
choices
getState
inRange
intInRange
noConflict
random
randomize
sample
setState
shuffle
$ npm install seeded-rand
只需下载dist / jsrand.min.js和(可选) dist / jsrand.mi
https://blogs.unity3d.com/cn/2015/01/07/a-primer-on-repeatable-random-numbers/ (英文原版)
http://www.manew.com/thread-37144-1-1.html
不管创建什么样的程序,几乎都离不开随机数.如果您想多次生成同样的结果,这就需要随机数是可重复的。
在本片文章中...
使用相同的随机种子,换一个设备,还能得到相同的随机序列吗?
由于对随机数的生成理解不够深刻,还引发了一次跟同事之间的小讨论。不知为不知,在这里承认自己以前对随机数理解有限,把过程和经验记录于此。
随机数的基础用法和特性
编程过程中,随机数的基础用法和特性广为人知。但为了防止有对这个概念还不清楚的新手,还是先简单说明一下。
编程获取随机数的基本做法是:
在程序初始...
Math.seededRandom = function (max, min) {
max = max || 1 //(设置最大值)
min = min || 0 //(设置最小值)
Math.seed = (Math.seed * 9301 + 49297) % 233280
var rnd = Math.seed / 233280.0
游戏中经常要用到随机数,但如果一个没有随机种子的的生成器,就没法重复之前的随机数了。js的Math.random就用不了随机种子,只好自己弄了一个,有了随机种子,每次只要传入相同的种子,都会得到同样的随机数。直接代码:
function seededRandom(seed, min, max) {
seed = (seed * 9301 + 49297) % 233280;
Javascript 的Math.random可以做前两个约束,但第三个是开放的,这就是问题所在; 如果您不能每次都可靠地重现相同的一组伪随机数,那么这又是另一个可能导致测试运行期间出现不必要差异的因素。
鉴于该库的性能也可能会有所不同并成为一个因素,因此有一个例程旨在生成一组给定长度的随机数。
这个库是模块化的。 它有一组通用函数和两个不同的生成器。
seed (x) :将生成器播种到x 。
generate() :生成一个介于 0 和 1 之间的浮点数。
generate (min, max) :在min和max之间生成一个浮点数。
integer () :生成 0 到 1 之间的整数。
integer (min, max) :生成
randoma用户友好的伪随机数生成器(PRNG),这在密码上是不安全的。
安装$ npm install randoma用法const Randoma = require('randoma');
const random =新的Random randoma用户友好的伪随机数生成器(PRNG),这在密码上不是安全的。
安装$ npm install randoma用法const Randoma = require('randoma');
const random = new Randoma({seed:10});
random.integer();
// => 2027521326 random.integer();
// => 677268843(新的Randoma({seed:':unicorn:'})。integer());
// => 1659974344(new Randoma({seed:':unicorn:'})。integer());
// => 1659974344 API const random = new Randoma(options)options类型:对象
有一个随机数生成器:首先输入一个正整数n表示要生成随机数的位数,然后它会生成一个n位的不包含前导数为0的正十进制数,生成器还有一个性质,就是它生成的第i位上(从左到右)的数字永远不等于i。
比如生成的位数长度为1的数,那它不能生成0和1,;如果位数为2,不能生成10,11,12,13,14,15,16,17,18,19,22,32,42,54,62,72,82,92
求给定输入n,它一共能生成
是的,JavaScript中的Math.random()生成的是伪随机数,但是可以使用真随机数生成器来生成0到23之间的真随机数。
一种方法是使用外部真随机数生成器API。例如,可以使用Random.org的API,该API提供了真正的随机数。您可以使用XMLHttpRequest向其API发送请求,并使用返回的随机数。
另一种方法是使用硬件随机数生成器。硬件随机数生成器是依赖于物理过程的设备,例如热噪声,放电噪声等。它们可以生成真正的随机数。在Web应用程序中,可以使用WebCrypto API中提供的硬件随机数生成器。
以下是使用Random.org API生成0到23之间的真随机数的示例代码:
```javascript
const xhr = new XMLHttpRequest();
xhr.open('GET', 'https://www.random.org/integers/?num=1&min=0&max=23&col=1&base=10&format=plain&rnd=new');
xhr.onload = function () {
if (xhr.status === 200) {
const randomNumber = parseInt(xhr.responseText);
console.log(randomNumber);
} else {
console.error('Error generating random number');
xhr.send();
请注意,这种方法需要从外部API获取真随机数,因此可能会受到网络延迟和其他问题的影响。
maystar_rnd: