所以我有这个&#39; *&#39;用vector<string>
制作。现在我需要生成六个数字,表示从1到N * N(这是方形的区域)的不同坐标,所以我可以改变它们。到目前为止我所拥有的是
#include <cstdlib>
#include <iostream>
int main(){
int N = 4, x, y;
srand(time(NULL));
for(int i = 0; i < 6; i++){
//generate 6 random coordinates
int rnd = rand() % (N*N-1) + 2;
if(rnd <= N){
x = rnd;
y = 0;
}
else{
if((x = (rnd % N) - 1) < 0){
x = rnd / N - 1;
y = x;
}
else y = rnd / N;
}
std::cout << "rnd: " << rnd << " x:" << x << " y:" << y << "\n\n";
}
}
但我一直得到相同的坐标。我的代码有缺陷还是我需要添加一些内容?
答案 0 :(得分:2)
您正在做一些奇怪的事情来获得x
和y
。它比你得到的要简单得多:
for(int i = 0; i < 6; i++){
// the square is N x N, so you want two numbers from 0 to N-1
int x = rand() % N;
int y = rand() % N;
std::cout << "x:" << x << " y:" << y << "\n\n";
}
可替换地:
for(int i = 0; i < 6; i++){
int rnd = rand() % (N*N);
int x = rnd % N;
int y = rnd / N;
std::cout << "rnd: " << rnd << " x:" << x << " y:" << y << "\n\n";
}
当然使用%
以这种方式获取随机数是一个糟糕的主意,rand()
的常见实现恰好在将多个值组合成坐标到多维空间时具有非常糟糕的特性:模式为likely to emerge。
相反,在将一个范围内的随机值操作到所需范围时需要注意。幸运的是,有人已经为你做了数学计算,你可以通过<random>
库来使用它。
#include <random>
std::mt19937 eng; // object which produces random bits
std::random_device r;
std::seed_seq seed{r(), r(), r(), r(), r(), r(), r(), r()};
eng.seed(seed); // seed the bit generator, replaces srand()
std::uniform_int_distribution<> dist(0, N-1); // encapsulates the correct method of turning
// random bits into random numbers in the range
// [0, N)
for(int i = 0; i < 6; i++) {
int x = dist(eng); // the distribution internally used the engine like rand()
int y = dist(eng);
std::cout << "x:" << x << " y:" << y << "\n\n";
}
或者:
std::random_device r;
std::seed_seq seed{r(), r(), r(), r(), r(), r(), r(), r()};
std::mt19937 eng(seed);
std::uniform_int_distribution<> dist(0, N*N - 1);
for(int i = 0; i < 6; i++) {
int rnd = dist(eng);
int x = rnd % N; // used of % here is just fine
int y = rnd / N;
std::cout << "rnd: " << rnd << " x:" << x << " y:" << y << "\n\n";
}
这是一个完整的程序,可以产生一个&#39; *&#39;在vector<string>
中,生成坐标并在方块中标记这些坐标:
http://coliru.stacked-crooked.com/a/e024212ebc951f92
结果如下:
**********
**********
**********
**********
**********
**********
**********
**********
**********
**********
x:0 y:7
x:0 y:2
x:6 y:8
x:5 y:0
x:4 y:7
x:0 y:2
***** ****
**********
*********
**********
**********
**********
**********
*** *****
****** ***
**********
答案 1 :(得分:1)
其他答案讨论srand(time(NULL))
那么,
这确保适用于随机数生成,无论两次调用之间的时间间隔如何。
您可以使用类似
的内容int Min, Max;
random_device rd; // non-deterministic generator
mt19937 gen(rd()); // to seed mersenne twister.
uniform_int_distribution<> dist(Min,Max); // distribute results between Min and Max inclusive.'
然后生成数字并使用
指定它int Rand=dist(gen);
不要忘记包含
<random>
答案 2 :(得分:0)
每次运行时都会得到不同的结果。但是请注意,时间(NULL)仅每秒更改一次,因此在相同的时间顺序秒内运行两次将生成相同的随机种子。
但是,您的代码还存在许多其他问题。你的数学错了。
1)
int rnd = rand() % (N*N-1) + 2;
这将始终产生至少为2的结果,因此您永远不会得到1的结果,其余代码似乎意图引用网格的左上角。所以,蝙蝠,你的随机公式是偏斜的。
2)
你的网格中有N * N个坐标。
rand() % *value*
除以“值”(假设值为正)的余数总是产生0和(值-1)之间的结果。毕竟:
0 % 4 = 0
1 % 4 = 1
2 % 4 = 2
3 % 4 = 3
4 % 4 = 0
所以:
rand() % (N*N-1)
这将始终产生0到N * N-2之间的结果。因此,如果N为4,则N * N-1为15,这将始终是0到14之间的结果,或者是随机坐标的15个可能值,而您的网格中确实有16个不同的坐标。
结论:
你的方法的整体问题源于人类自然倾向于从1开始,然后是2开始编号,等等;在处理计算机代码和算法时,从0开始,而不是1开始编号的事情更为自然。
当发生这种情况时,你的整个随机坐标生成变得很简单:
int rnd = rand() % (N*N);
int x= rnd % N;
int y= rnd / N;
就是这样。无论如何都不需要那种笨拙的if
装置。