我想生成一系列“随机”唯一数字,用于纸牌游戏!这些数字应该在0到81之间。 在这个阶段我不关心安全性或速度,我只想要一些简单的工作。
在我的下面的代码中,我设法在数组中创建了2个唯一的随机数,但其余的10个数字不会改变,但保留-1作为初始值。 我已经找到了更准确的随机数生成方法,但我会在稍后阶段检查它们!
ImageView mImageViewFilling = (ImageView) findViewById(R.id.animated_imageview);
((AnimationDrawable) mImageViewFilling.getBackground()).start();
答案 0 :(得分:1)
您的代码有我见过的一种奇怪的缩进和支撑布局方案:
#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]);
}
转换为更正统的风格(奥尔曼,或多或少 - 见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 - 特别是如果您要使用系统生成的种子(例如当前时间)。
答案 1 :(得分:0)
出于建议的目的(生成0到81之间的随机数字序列,其中每个项目与其他项目不同),您将需要一种特定类型的随机数生成器(RNG),一种可以生成所有可能的随机数生成器82个项目的排列(表示为82!
或82个阶乘)。但是,只有有限的RNG才能做到这一点。特别是C rand()
函数的实现是未指定的,因此不能保证生成那么多的排列。
伪随机数生成器(PRNG,这里使用的一种RNG)不能生成比其周期更多的随机数序列。对于82!
排列,没有周期小于82!
的PRNG可以做到这一点(2的最高幂2是2 408 ,这意味着生成器需要在至少408位,或51字节,很可能这样做 - 而51字节比srand
通常要大得多。或者,为此目的,建议您使用生成“不可预测”数字的RNG,C语言和C库都不包含标准。有关详细信息,请参阅my article on randomness中的“随机播放”和“不可预知的RNG”。