什么是使用C ++中的游戏一个好的随机数发生器?
我的考虑是:
- 随机数的大量需要,所以速度还是不错的。
- 玩家将总是抱怨的随机数,但我希望能够将它们指向解释说,我真的没有我的工作提供参考。
- 由于这是我没有太多的时间用于商业项目,如果该算法无论是)是比较容易实现或b)具有良好的非GPL的实现提供这将是很好。
- 我已经使用
rand()
在相当多的地方,所以任何其他发电机最好是好来证明它需要的所有更改。
我不知道太多关于这个主题,所以我能想出的唯一办法是梅森难题 ; 它满足所有这些要求? 是否还有其他更好?
编辑:梅森难题似乎是一致的选择。 但是关于点#4是什么? 难道真的是大大优于rand()
编辑2:我是在2点更清晰一点:有没有办法让玩家通过了解随机数作弊。 期。 我希望它足够随机的人(至少是那些谁知道随机性)不能抱怨,但我并不担心预测。 这就是为什么我把速度作为首要考虑因素。
编辑3:我倾向于在马尔萨利亚的RNG了,但我还是想更多的投入。 因此,我设置了一个赏金。
编辑4:刚一说明:我打算在午夜之前UTC接受的答案今日(避免与人的代表盖搞乱)。 所以,如果你想回答的,不要等到最后一分钟!
另外,我喜欢马尔萨利亚的XORshift发电机的外观。 有没有人有任何关于他们的输入?
Answer 1:
乔治马尔萨利亚已经开发了一些最好最快的RNG现有的乘用携带的是一个显着的一个均匀分布。
===更新2018年9月12日===
对于我自己的工作,我现在用的Xoshiro256 ** ,这是一种对马尔萨利亚的XorShift进化/更新。
Answer 2:
有时,游戏开发商不想真正的随机性和洗牌袋是比较合适的。
如果你想随机性,梅森捻线机满足您的要求。 它是快速,统计学随机的,有很长的时期,有很多实现的在那里。
编辑: rand()
典型地实施为线性同余发生器 。 如果你做的它是否是你的目的不够好一个明智的选择可能最好。
Answer 3:
还有比梅森难题现在好得多的选择。 下面是一个叫做WELL512 RNG,由梅森的设计师设计,开发10年后,和游戏的各地更好的选择。 该代码被放在由克里斯Lomont博士的公共领域。 他声称这实现比梅森快40%,不贫困的扩散和捕获时遭受的状态包含许多0位,显然是有很多简单的代码。 它的周期是2 ^ 512; 电脑接管10 ^ 100年的循环状态,所以它足够大。
这里是一纸overviewing的PRNG在那里我找到了WELL512实施。 http://www.lomont.org/Math/Papers/2008/Lomont_PRNG_2008.pdf
所以 - 更快,更简单,由同一个设计师设计的10年后,比梅森产生更好的数字。 你怎么会弄错? :)
UPDATE(14年11月18日):固定误差(变更0xDA442D20UL到0xDA442D24UL,如在上述联的论文中描述)。
/* initialize state to random bits */
static unsigned long state[16];
/* init should also reset this to 0 */
static unsigned int index = 0;
/* return 32 bit random number */
unsigned long WELLRNG512(void)
{
unsigned long a, b, c, d;
a = state[index];
c = state[(index+13)&15];
b = a^c^(a<<16)^(c<<15);
c = state[(index+9)&15];
c ^= (c>>11);
a = state[index] = b^c;
d = a^((a<<5)&0xDA442D24UL);
index = (index + 15)&15;
a = state[index];
state[index] = a^b^d^(a<<2)^(b<<18)^(c<<28);
return state[index];
}
Answer 4:
梅森难题是行业典型,特别是因为它很适合SIMD和可制成超快。 克努特是太受欢迎(感谢,大卫)。
在大多数游戏应用程序的速度确实是关键因素,因为球员都抱怨低帧率很多比他们更会抱怨事实,那就是对产生3时,它是由7,2之前略有偏差,和图9的顺序。
当然,唯一的例外是赌博的钱,但你的相关发牌当局将特别制定出可以使用的算法。
Answer 5:
买一个便宜的网络摄像头,一个电离烟雾探测器。 拆开他们两个,烟雾探测器含有少量放射性物质 - γ波的来源 - 这将导致在您的网络摄像头发射的光子。 那是你真正的随机源:)
Answer 6:
梅森倍捻机是非常好的,而且速度快为好。 我用它在游戏,它并不难在所有能够实现或使用。
该井随机算法被设计为在梅森倍捻机的改善。 游戏宝石 7有更多信息。 就可以了,如果你能借用或拥有它。
在该井页我联系你,这个数字是该算法的周期。 也就是说,你可以得到2 ^ N - 1个的数字,它需要补种,其中N是前:512,1024,19937,或44497.梅森倍捻机的周期为N = 19937,或2 ^ 19937 - 1.你会看到这是一个非常大的数字 :)
我可以指出的唯一的另一件事是, 升压有一个随机库 ,你应该找到有用的。
在回答您的编辑,是扭腰或井,除兰特好得多()。 此外,旧模把戏损害了数分布。 更有理由使用boost :)
Answer 7:
在实时游戏,有没有办法让一个球员,以确定一个“好”发电机和一个“坏”之间的区别。 在回合制游戏中,你是对的 - 狂热者的一些少数人会抱怨。 他们甚至会告诉你的故事,在痛苦的细节,你如何毁了他们的生活有一个坏的随机数发生器。
如果你需要一个真正的一串随机数字(和你是一个在线游戏),你可以得到一些在Random.org 。 他们使用基于回合制游戏,或作为种子实时游戏。
Answer 8:
我的粉丝以撒 ,不像mersense捻线机,它的crypographically安全的,(你无法通过观察辊破解期)
IBAA (RC4?)也是一个被使用的暴风雪 ,以防止有人预测用于战利品辊上的随机数..我想类似的,当你在玩断battle.net服务器的完成W /暗黑破坏神II东西。
*不能在任何合理时间(几百年?)
Answer 9:
基于由Ian C.布拉德随机数生成器:
// utils.hpp
namespace utils {
void srand(unsigned int seed);
void srand();
unsigned int rand();
}
// utils.cpp
#include "utils.hpp"
#include <time.h>
namespace {
static unsigned int s_rand_high = 1;
static unsigned int s_rand_low = 1 ^ 0x49616E42;
}
void utils::srand(unsigned int seed)
{
s_rand_high = seed;
s_rand_low = seed ^ 0x49616E42;
}
void utils::srand()
{
utils::srand(static_cast<unsigned int>(time(0)));
}
unsigned int utils::rand()
{
static const int shift = sizeof(int) / 2;
s_rand_high = (s_rand_high >> shift) + (s_rand_high << shift);
s_rand_high += s_rand_low;
s_rand_low += s_rand_high;
return s_rand_high;
}
为什么?
- 非常非常快
- 更高的熵比大多数标准
rand()
实现 - 容易明白
Answer 10:
你应该考虑另外一个标准是线程安全的。 (你应该使用在今天的多核环境中的线程。)刚刚从多个线程可以胡来调用兰德与它的确定性的行为(如果你的游戏依赖于)。 至少,我建议您切换到rand_r。
Answer 11:
我会投票给梅森倍捻机为好。 实现被广泛使用,它有一个非常大的周期为2 ^ 19937 -1是相当快的,并经过最随机性测试包括马尔萨利亚开发的顽固分子测试。 兰特()和Co.,被装码组,产生低质量的偏离及其连续的值可以容易地推断。
值得注意的一点,然而,就是要正确种子MT成通过随机性测试的状态。 通常喜欢drand48一个LCG()被用于该目的。
我想说的MT满足您已设置(可证)的所有要求,而且它会是一个矫枉过正去像MWCG海事组织。
Answer 12:
GameRand实现在此发布的算法http://www.flipcode.com/archives/07-15-2002.shtml
这是我原来在80年代末开发的。 它轻松击败兰特()的数值质量的期限,并作为附带的好处是最快的随机算法可能。
Answer 13:
我希望它足够随机的人(至少是那些谁知道随机性)不能抱怨,但我并不担心预测。
A-HA!
有你的实际需求!
没有人可以指责你为这个应用程序使用Mersenne扭曲。
Answer 14:
根据目标操作系统上,您可能能够使用/ dev /随机的。 它并不真正需要的任何执行,并在Linux(也许其他一些操作系统)这是真正的随机。 读取块,直到有足够的熵是可用的,所以你可能需要阅读的文件,并使用另一个线程将其存储在缓冲区或东西。 如果你不能使用阻塞读取通话时,您可以使用/ dev / urandom的。 它产生的随机数据差不多,也是为/ dev /随机的,但它重用一些随机数据,立即给输出。 这不是为安全,但它可能取决于你打算用它做什么工作的罚款。
Answer 15:
显然,(我忘了,我读它,就像我忘了,我读了咖喱是好的,防止altzheimas),采取新生成的GUID的校验和的绝对值是很好的随机的。 这是一个大的数字,你可以使用它的一个模萎缩下来。
因此,在SQL(我区),这是ABS(校验和(NEWID()))%1000
抢
Answer 16:
你知道吗? 原谅我,如果你觉得这个答案完全吸...但我一直在使用(对于只有上帝知道什么原因......) DateTime.Now.Milliseconds
作为一种方式来获得一个随机数。 我知道这不是完全随机的,但它似乎是...
我只是不能打扰打字这么多只是为了获得一个随机数! :P
文章来源: What is a good random number generator for a game?