从10x10阵列开始,如何选择10个随机站点

时间:2012-03-13 01:41:09

标签: c random

我正在尝试编写C代码,从10x10的网格中随机选择10个随机网站。我正在考虑的方法是在零和RAND_MAX之间为每个单元分配一个随机数,然后选出10个最小/最大值。但我对如何实际编码这样的东西知之甚少:/

之前我使用过伪随机数生成器,所以我可以做那个部分。

6 个答案:

答案 0 :(得分:1)

只需在0到9之间生成2个随机数,然后从数组中选择随机元素,如:

arr[rand1][rand2];

循环执行10次。没有必要让它变得更复杂。

答案 1 :(得分:1)

为了略微简化,将10x10阵列视为100个元素的等效线性阵列。现在问题变成从一组100中挑选10个不同的数字。要获得第一个索引,只需选择0到99范围内的随机数。

int hits[10];  /* stow randomly selected indexes here */
hits[0] = random1(100);  /* random1(n) returns a random int in range 0..n-1 */

第二个数字几乎一样容易。从剩余的99种可能性中选择另一个数字。 Random1返回一个连续范围为0..99的数字;然后你必须将它映射到破碎范围0..hits [0] -1,命中[0] + 1..99。

hits[1] = random1(99);
if (hits[1] == hits[0]) hits[1]++;

现在对于第二个数字,映射开始变得有趣,因为它需要一些额外的工作来确保新数字与现有选择不同。

hits[2] = random1(98);
if (hits[2] == hits[0]) hits[2]++;
if (hits[2] == hits[1]) hits[2]++;
if (hits[2] == hits[0]) hits[2]++; /* re-check, in case hits[1] == hits[0]+1 */

如果您按顺序对命中数组进行排序,则可以避免重新检查元素的唯一性。把所有东西放在一起:

int hits[10];
int i, n;
for (n = 0; n < 10; n++) {
    int choice = random1( 100 - n );  /* pick a remaining index at random */
    for (i = 0; i < n; i++) {
        if (choice < hits[i])  /* find where it belongs in sorted hits */
            break;
        choice++;  /* and make sure it is distinct *
                   /* need ++ to preserve uniform random distribution! */
    }
    insert1( hits, n, choice, i );
            /* insert1(...) inserts choice at i in growing array hits */
}

您可以使用hits从10x10数组中获取元素,如下所示:

array[hits[0]/10][hits[0]%10]

答案 2 :(得分:0)

for (int i = 0; i < 10; i++) {
    // ith random entry in the matrix
    arr[rand() % 10][rand() % 10];
}

答案 3 :(得分:0)

从Peter Raynham的回答中修改了这个 - 我认为其中的想法是对的,但是他的执行过于复杂,并没有正确映射范围:

为了略微简化,将10x10阵列视为100个元素的等效线性阵列。现在问题变成从一组100中挑选10个不同的数字了。

要获取第一个索引,只需选择0到99范围内的随机数。

int hits[10];  /* stow randomly selected indexes here */
hits[0] = random1(100);  /* random1(n) returns a random int in range 0..n-1 */

第二个数字几乎一样容易。从剩余的99种可能性中选择另一个数字。 Random1返回一个连续范围为0..99的数字;然后你必须将它映射到破碎范围0..hits [0] -1,命中[0] + 1..99。

hits[1] = random1(99);
if (hits[1] >= hits[0]) hits[1]++;

请注意,您必须将完整的点击次数[0] .. 98映射到点击次数[0] + 1..99

对于另一个号码,您必须与之前的所有号码进行比较,因此对于您必须执行的第三个号码

hits[2] = random1(98);
if (hits[2] >= hits[0]) hits[2]++;
if (hits[2] >= hits[1]) hits[2]++;

您无需对数字进行排序!把所有东西放在一起:

int hits[10];
int i, n;
for (n = 0; n < 10; n++) {
    int choice = random1( 100 - n );  /* pick a remaining index at random */

    for (i = 0; i < n; i++)
        if (choice >= hits[i])
            choice++;

    hits[i] = choice;
}

您可以使用hits从10x10数组中获取元素,如下所示:

array[hits[0]/10][hits[0]%10]

答案 4 :(得分:0)

如果您希望从网格中选择的随机单元格是唯一的 - 您似乎真的想要构造随机排列。在那种情况下:

  • 将单元格编号0..99放入1D数组
  • 拿一些shuffle algorithm并用它抛出那个数组
  • 从混洗阵列中读取前10个元素。

缺点:该算法的运行时间随着细胞数量的增加而线性增加。因此,出于实际原因,最好像@ PaulP.R.O一样。说...

答案 5 :(得分:0)

hjhill的解决方案中存在一个微妙的错误。如果不对列表中的元素进行排序,那么当您扫描列表(内部for循环)时,无论何时碰到选择索引(choice++),都需要重新扫描。这是因为您可能会将其添加到列表中的上一个条目中 - 例如,使用随机数:90,89,89。

完整的代码:

int hits[10];
int i, j, n;
for (n = 0; n < 10; n++) {
    int choice = random1( 100 - n );  /* pick a remaining index at random */
    for (i = 0; i < n; i++) {
        if (choice >= hits[i]) {   /* find its place in partitioned range */
            choice++;
            for (j = 0; j < i; j++) {   /* adjusted the index, must ... */
                if (choice == hits[j]) {  /* ... ensure no collateral damage */
                    choice++;
                    j = 0;
                }
            }
        }
    }
    hits[n] = choice;
}

我知道它有五个级别的嵌套有点难看。当仅选择几个元素(例如,100个中的10个)时,它将具有比分类解决方案更好的性能;当选择大量元素(例如,100个中的90个)时,性能可能会比排序解决方案更差。