如何使用rand()函数生成一个以前未生成的数字?

时间:2018-07-21 15:12:29

标签: c random

//这是我的示例所显示的意思:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int i;
int a;


for (a = 0;a <10;a ++) {
    i = (rand()%10)+1; // generates a number from 1-10
    printf("%d\n", i);
}

//我希望循环生成一个数字,该数字给出以前没有生成的数字。例如,输出如下:

1,3,6,2,8,9,4,10,5,7

代替:

3,9,10,3,7,9,2,7,10,1

换句话说,我不想要任何副本。

2 个答案:

答案 0 :(得分:2)

您显然不只是想要没有副本,而且您想要给定集合中的每个数字仅一次。正如罗伯特(Robert)所说,这类似于洗牌。您在C中没有“套牌”,但是您可以将其建模为数组:

int deck[] = {1,1,1,1,1,1,1,1,1,1};

这应该代表10个不同的“卡”(由它们在数组中的索引标识),每个卡都可以使用一次。现在,只需编写“绘制”卡片的代码:

int i = 0;  // starting point for searching for the next card to draw
for (int n = 10; n > 0; --n)  // how many cards are left
{
    int skip = rand() % n;  // randomly skip 0 .. n cards
    while (1)
    {
        if (deck[i])             // card still available?
        {
            if (!skip) break;    // none more to skip -> done
            --skip;              // else one less to skip
        }

        if (++i > 9) i = 0;      // advance index, wrapping around to 0
    }
    deck[i] = 0;              // draw the card
    printf("%d\n", i+1);      // and print it out
}

当然,请先播种PRNG(例如srand(time(0))),以免每次获得的序列都不相同。

答案 1 :(得分:0)

问题中显示的想法是打印一定范围内的数字,而不要重复。通过将每个值放入数组并在其周围交换其元素,这是一种方法。

一种变化可能是您不想使用所有可能的数字,在这种情况下,只需更改PICKED

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define ARRLEN 10
#define PICKED 10

int main(void) { 
    int array[ARRLEN];

    srand((unsigned)time(NULL));        // seed the PRNG

    for(int i = 0; i < ARRLEN; i++) {       // generate the numbers
        array[i] = i + 1;
    }

    for(int i = 0; i < ARRLEN; i++) {       // shuffle the array
        int index = rand() % ARRLEN;
        int temp = array[i];
        array[i] = array[index];        // by randomly swapping
        array[index] = temp;
    }

    for(int i = 0; i < PICKED; i++) {       // output the numbers
        printf("%d ",  array[i]);
    }
    printf("\n");
}

程序输出:

9 8 4 5 1 10 7 3 6 2

该库的PRNG并不是很随机,但是在许多情况下这并不重要。如果可以,则可以使用更好的算法。