【问题标题】:Create random numbers创建随机数
【发布时间】:2012-12-23 12:25:41
【问题描述】:

这是我在这里的第一个问题,我正在制作一个小游戏,为了分配角色,我需要随机数。我有这个代码,但是数字可能不重复吗?谢谢。

void giveroles() {
    srand(time(NULL));
    int r = rand() % i + 1; 
    switch ( r ) { /* ... */ }
}

【问题讨论】:

  • 在linux系统中也可以阅读/dev/randdom
  • @shiplu.mokadd.im 如果您的系统没有足够的熵,这可能需要 很长时间 时间。使用 /dev/urandom 更快,尽管可能不是那么随机数。

标签: c random


【解决方案1】:

如果您想随机分配一小组数字,而不是随机生成它们,请创建所需数字的列表,然后随机化列表的顺序(遍历列表,随机交换条目)。

例如:

int cards[52];
for(int i = 0 ; i < 52 ; i++)
{
    cards[i] = i;
}
for(int i = 0 ; i < 1000 ; i++)
{
    int r1 = rand()%52;
    int r2 = rand()%52;
    int t = cards[r1];
    cards[r1] = cards[r2];
    cards[r2] = t;
}
for(int i = 0 ; i < 52 ; i++)
{
    printf("%d\n", cards[i]);
}

为了完整起见,有人指出以这种方式洗牌是有偏见的。这是一个不偏不倚的变体:

cards[0] = 0;
for(int i = 1 ; i < 52 ; i++)
{
    int r = rand() % (i+1);
    cards[i] = cards[r];
    cards[r] = i;
}

(需要进一步说明的是,取rand()的取模也可能有偏差,因为rand()的取值范围不会是偶数)

【讨论】:

  • 谢谢@JasonD,我刚刚尝试了类似的方法并且成功了:P
  • 洗牌是个好主意,但这种洗牌会导致输出有偏差——并不是所有的安排都有同样的可能性。试试Fisher-Yates shuffle,它还允许在洗牌时初始化数组
  • true,而rand()%x 也有偏见。不过,我怀疑这并不重要。
【解决方案2】:

取出线srand(time(NULL));。通常,您应该只在程序中执行一次此操作,例如在main() 的开头,以随机化后续调用rand() 使用的种子。

【讨论】:

    【解决方案3】:

    如果您不想重复随机数,解决方案是跟踪您之前使用过哪些随机数,如果您在现有数字列表中获得“命中”,请重试。

    另外,使用srand(time(NULL)); 只能使用一次。我怀疑这更像是您实际提出的问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-30
      • 2013-01-25
      • 2012-02-21
      • 2016-10-07
      • 2015-04-17
      • 2011-11-29
      相关资源
      最近更新 更多