【问题标题】:Generate different random coordinates [closed]生成不同的随机坐标[关闭]
【发布时间】:2014-09-28 14:54:51
【问题描述】:

所以我用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";
        }

}

但我一直得到相同的坐标。我的代码有缺陷还是我需要添加一些东西?

【问题讨论】:

  • here 它可以工作(显然是伪随机的)...
  • srand 每秒只会改变一点点值,所以如果你连续两次运行这段代码,我希望你确实得到相同/相似的结果。这与“随机种子”的工作方式有关 - 您的种子仅在下一秒从 111318789 变为 111318790,它并不像数字中的每一位都打乱。您可以尝试使用“get nano second time”,或者您可以在两次运行之间等待更长的时间......
  • @MatsPetersson 会试试的
  • @0d0a 生成 7 三次
  • @MatsPetersson 我怎样才能第二次获得纳米,在谷歌上没有找到任何东西

标签: c++ random coordinates


【解决方案1】:

你正在做一些奇怪的事情来获得xy。它比你所拥有的要简单得多:

    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() 的常见实现恰好在将多个值组合成多维空间的坐标时具有非常糟糕的特性:模式是@ 987654321@.

当您将随机值从一个范围操作到所需范围时,您需要小心。幸运的是,有人已经为您完成了数学运算,您可以通过 &lt;random&gt; 库来使用它。

#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";
}

这是一个完整的程序,它在vector&lt;string&gt; 中生成一个“*”的正方形,生成坐标并在正方形中标记这些坐标:

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

***** ****
**********
 *********
**********
**********
**********
**********
 *** *****
****** ***
**********

【讨论】:

  • 帮我省了不少麻烦,谢谢 :)
【解决方案2】:

其他答案讨论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>

【讨论】:

  • 这就是我想要的,谢谢
【解决方案3】:

每次运行它都会得到不同的结果。但请注意,time(NULL) 每秒只更改一次,因此在同一时间顺序内运行两次将产生相同的随机种子。

但是,您的代码还存在许多其他问题。你的数学错了。

1)

int rnd = rand() % (N*N-1) + 2;

这将始终产生至少 2 的结果,因此您永远不会得到 1 的结果,其余代码似乎打算引用网格的左上角。所以,一开始,你的随机公式就出现了偏差。

2)

您的网格中有 N*N 个坐标。

rand() % *value*

除以“值”的余数(假设该值为正数)始终产生介于 0 和 (value-1) 之间的结果,包括 0 和 (value-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 装置,无论如何。

【讨论】:

  • 取第一个坐标和最后一个坐标,这样我就加了2个
  • 存在尴尬的情况,因为这些坐标与vector&lt;string&gt;一起使用,所以v[y][x]
猜你喜欢
  • 2021-10-03
  • 2022-01-18
  • 1970-01-01
  • 2015-03-08
  • 1970-01-01
  • 2023-01-07
  • 1970-01-01
  • 2013-02-08
相关资源
最近更新 更多