我尝试着创造一款带有骰子的游戏,我需要在其中添加一些随机数字(游戏邦注:即模拟骰子的边缘)。我知道如何在1到6之间
#include <cstdlib>
#include <ctime>
#include <iostream>
using namespace std;
int main()
{
srand((unsigned)time(0));
int i;
i = (rand()%6)+1;
cout << i << "\n";
}
并不是很好地工作,因为当我运行程序几次,这是我得到的输出:
6
1
1
1
1
1
2
2
2
2
5
2
所以我想要一个每次生成不同随机数的命令,而不是连续5次生成相同的随机数。是否有这样的命令?
我知道如何在c++中生成随机数,而不使用任何标头,编译器intrinsic或任何东西。
#include <cstdio> // Just for printf
int main() {
auto val = new char[0x10000];
auto num = reinterpret_cast<unsigned long long>(val);
delete[] val;
num = num / 0x1000 % 10;
printf("%llu\n", num);
}
在运行一段时间后,我得到了以下数据:
0: 5268
1: 5284
2: 5279
3: 5242
4: 5191
5: 5135
6: 5183
7: 5236
8: 5372
9: 5343
看起来是随机的。
工作原理:
现代编译器使用ASLR(地址空间布局随机化)防止缓冲区溢出。
你可以不使用任何库生成一些随机数,这只是为了好玩。不要那样使用ASLR。
使用模数可能会在随机数中引入偏置,这取决于随机数生成器。更多信息请看这个问题。当然,在随机序列中得到重复的数字是完全可能的。
尝试一些c++ 11特性以获得更好的分发:
#include <random>
#include <iostream>
int main()
{
std::random_device dev;
std::mt19937 rng(dev());
std::uniform_int_distribution<std::mt19937::result_type> dist6(1,6); // distribution in range [1, 6]
std::cout << dist6(rng) << std::endl;
}
有关c++ 11随机数的更多信息,请参阅此问题/答案。上面的方法并不是唯一的方法,但它是一种方法。
可以从这里获得生成随机数的完整随机类代码!
如果你在项目的不同部分需要随机数,你可以创建一个单独的类Randomer来封装它里面的所有随机内容。
就像这样:
class Randomer {
// random seed by default
std::mt19937 gen_;
std::uniform_int_distribution<size_t> dist_;
public:
/* ... some convenient ctors ... */
Randomer(size_t min, size_t max, unsigned int seed = std::random_device{}())
: gen_{seed}, dist_{min, max} {
}
// if you want predictable numbers
void SetSeed(unsigned int seed) {
gen_.seed(seed);
}
size_t operator()() {
return dist_(gen_);
}
};
这样的类以后会很方便:
int main() {
Randomer randomer{0, 10};
std::cout << randomer() << "\n";
}
你可以检查这个链接作为一个例子,我如何使用这样的Randomer类生成随机字符串。如果你愿意,你也可以使用Randomer。