我有一个启动许多客户端进程的bash脚本。这些是人工智能游戏玩家,我用它来测试一个拥有400个连接的玩家的游戏。
我遇到的问题是AI播放器使用
srand( time(nullptr) );
但如果所有玩家大约在同一时间开始,他们将经常收到相同的time()值,这意味着他们都在同一个rand()序列中。
测试过程的一部分是确保如果大量客户端几乎同时尝试连接,服务器就可以处理它。
我曾考虑使用像
这样的东西srand( (int) this );
或类似的,基于每个实例都有唯一内存地址的想法。
还有另一种更好的方式吗?
答案 0 :(得分:3)
将随机种子用于伪随机生成器。
std::random_device
是昂贵的随机数据。 (昂贵,如慢)
您可以使用它来播种prng算法。 mt19937是您需要的最后一个prng算法。
如果您的需求需要,您可以选择通过分发方式进行操作。即如果您需要的值不是发电机提供的某个范围。
std::random_device rd;
std::mt19937 generator(rd());
答案 1 :(得分:3)
这些天rand()
和srand()
已过时。
普遍接受的方法是从std::random_device
播种伪随机数生成器。在提供非确定性随机源的平台上,std::random_device
需要使用它们来提供高质量的随机数。
然而,在收集足够的熵时它可能很慢甚至阻塞。因此,它通常仅用于提供种子。
高质量但高效的随机引擎是标准库提供的 mersenne twister :
inline
std::mt19937& random_generator()
{
thread_local static std::mt19937 mt{std::random_device{}()};
return mt;
}
template<typename Number>
Number random_number(Number from, Number to)
{
static_assert(std::is_integral<Number>::value||std::is_floating_point<Number>::value,
"Parameters must be integer or floating point numbers");
using Distribution = typename std::conditional
<
std::is_integral<Number>::value,
std::uniform_int_distribution<Number>,
std::uniform_real_distribution<Number>
>::type;
thread_local static Distribution dist;
return dist(random_generator(), typename Distribution::param_type{from, to});
}
答案 2 :(得分:2)
如果您想要可重现的结果,则使用随机数种子和仅。这对于地图生成这样的事情来说非常方便,你想让地图随机化,但你希望它可以根据种子预测为随机。
对于大多数情况,你不想要它,你想要实际的随机数,最好的方法是通过标准库生成器函数:
#include <random>
std::random_device rd;
std::map<int, int> hist;
std::uniform_int_distribution<int> dist(0, 5);
int random_die_roll = dist(rd);
在这种情况下,不需要也不推荐种子。 &#34;随机设备&#34;关于正确播种PRNG(伪随机数发生器)以确保不可预测的结果。
同样,不要使用srand(time(NULL))
,因为它是一种非常古老,非常糟糕的初始化随机数的方法,并且它具有高度可预测性。在现代计算机上,通过一百万种可能的种子来寻找匹配的输出是微不足道的。