您的代码有我见过的最奇怪的缩进和大括号布局方案之一:
#include <stdio.h>
#include <stdlib.h>
int getRandomNumber(int Min, int Max)
{
double rnd= (double)rand()/((double)RAND_MAX+1);
return (int)(rnd*(Max-Min+1))+Min;
}
int main()
{
int j,counter,temp,deck[13];
srand(time(NULL));
int i;
counter=1;
for (i=0;i<12;i++)
{deck[i]=-1;
temp = getRandomNumber(0,81);
for (j=0;j<=i;j++)
{if (temp==deck[j])
{counter=0;}
if (counter!=0)
deck[i]=temp;
}
}
for(i=0;i<12;i++)
printf("%d ",deck[i]);
}
转换为更正统的风格(Allman,或多或少——参见维基百科Indent style),你会得到:
#include <stdio.h>
#include <stdlib.h>
static int getRandomNumber(int Min, int Max)
{
double rnd = (double)rand() / ((double)RAND_MAX + 1);
return (int)(rnd * (Max - Min + 1)) + Min;
}
int main(void)
{
int j, counter, temp, deck[13];
srand(time(NULL));
int i;
counter = 1;
for (i = 0; i < 12; i++)
{
deck[i] = -1;
temp = getRandomNumber(0, 81);
for (j = 0; j <= i; j++)
{
if (temp == deck[j])
{
counter = 0;
}
if (counter != 0)
deck[i] = temp;
}
}
for (i = 0; i < 12; i++)
printf("%d ", deck[i]);
}
需要static 和int main(void) 才能使代码通过我的默认编译选项;否则,它们是化妆品。
现在我们可以看到一些问题。将counter 设置为1 一次,在外循环之外;它有时会在循环内设置为0,但一旦发生,它就永远不会重置为1,因此不会向deck 添加更多数字。你需要重做内部循环,可能是这样的:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
static int getRandomNumber(int Min, int Max)
{
double rnd = (double)rand() / ((double)RAND_MAX + 1);
return (int)(rnd * (Max - Min + 1)) + Min;
}
int main(void)
{
int deck[13];
srand(time(NULL));
for (int i = 0; i < 12; i++)
{
int temp = getRandomNumber(0, 81);
deck[i] = -1;
int counter = 1;
for (int j = 0; j <= i; j++)
{
if (temp == deck[j])
{
counter = 0;
break;
}
}
if (counter != 0)
deck[i] = temp;
else
i--; // Try again with a new random choice for the same i
}
const char *pad = "";
for (int i = 0; i < 12; i++)
{
printf("%s%d", pad, deck[i]);
pad = " ";
}
putchar('\n');
return 0;
}
我不喜欢尾随空格,因此打印循环会注意确保没有尾随空格。
getRandomNumber() 的示例输出 — 在 macOS Sierra 10.12.2 和 GCC 6.3.0 上:
7 73 38 61 11 13 41 66 29 39 72 20
7 2 18 17 54 31 45 40 34 22 63 16
7 13 80 54 16 49 14 58 28 53 23 26
7 24 60 10 67 53 69 32 23 2 66 12
7 34 40 48 21 3 57 43 6 18 27 80
7 45 20 3 65 21 61 17 12 69 66 27
7 67 62 78 70 57 68 46 9 2 72 39
7 77 41 34 32 75 72 20 64 78 33 25
7 6 21 72 76 11 75 38 73 27 64 33
7 17 1 27 37 28 80 49 12 67 59 36
第一个数字并不是很随机——在一系列测试之后不久,它从 7 变为 8,但同样非随机。替代
生成随机数的方法是:
static int getRandomNumber(int Min, int Max)
{
int rnd;
int range = (Max - Min + 1);
while ((rnd = rand()) > RAND_MAX - (RAND_MAX % range))
;
return (rnd % range) + Min;
}
这避免了 82 不完全除以 RAND_MAX 这一事实的偏差,这将使较低数字的分布权重略高于 0..81 范围内的较高数字。它还避免了意外一致的第一个数字,尽管当测试以 1 秒的间隔运行时,新的第一个数字也是半可预测的。
示例结果:
48 33 28 78 14 2 81 13 23 75 38 40
45 42 74 1 11 68 17 33 78 49 23 80
42 51 38 3 5 52 35 56 54 23 59 41
39 60 2 8 36 53 79 30 72 75 62 37
36 69 45 10 78 20 71 17 6 53 54 30
33 78 9 15 75 7 40 61 27 36 70 68
30 5 55 17 69 73 25 63 37 1 21 71
27 14 19 66 57 43 1 13 3 65 71 21
24 26 62 63 41 61 68 28 67 20 74 17
21 35 26 57 28 79 47 44 2 52 60 77
注意第一个数字减3;第二个似乎增加了 9;呃——随机性并不是那么好。众所周知,rand() 通常不是一个高质量的 PRNG(伪随机数生成器),但我对这种明显的系统行为感到有点惊讶,种子每次相差 1。
在我的 Mac 上,当我将 srand() 更改为 srandom() 并将 rand() 更改为 random() 时,我得到了更好的(如,更不可预测的)结果:
29 1 7 11 25 52 63 15 26 55 75 64
40 4 64 18 8 57 73 27 38 15 60 28
43 3 27 17 1 58 26 72 73 18 20 7
76 16 27 43 64 20 63 30 35 17 33 57
79 47 32 33 6 30 35 7 38 55 25 61
69 57 79 75 15 54 5 35 21 46 65 61
30 79 66 14 56 39 19 8 50 47 76 33
62 65 81 44 52 39 25 30 54 12 24 68
27 49 60 72 53 35 14 41 63 46 45 65
67 39 9 11 60 19 64 73 43 17 21 26
random() 的 Mac 手册页仍然建议使用arc4random(),但这比普通的rand() 要好得多。您在其他系统上找到的内容将取决于系统提供的设施 — rand() 可能不像在 Mac 上看起来那么糟糕。基本上,在选择 PRNG 时要谨慎——尤其是如果您要使用系统生成的种子(例如当前时间)。