0

我在这部分的代码中遇到了问题:

Random rand = new Random();
string[] MyRandomArray = choices.OrderBy(x => rnd.Next()).ToArray();
string[] newArray = new string[4];

int num = 0;

for (num = 0; num < 3; num++)
{
    newArray[num] = MyRandomArray[num];
}

newArray[num] = "1";

string[] finalArray = newArray.OrderBy(x => rnd.Next()).ToArray();
this.radioButton1.Text = newArray[0];
this.radioButton2.Text = newArray[1];
this.radioButton3.Text = newArray[2];
this.radioButton4.Text = newArray[3];

我要做的是在单选按钮 1、2、3 和 4 的 newArray 中获取不同的数组位置。但是,我在分配的最后一个数组中遇到了问题。它不包含在随机播放中,因此我得到的唯一随机值是单选按钮 1、2 和 3。每当我尝试重新启动程序时,单选按钮 4 保持不变。

4

1 回答 1

0

关于随机抽样和潜在问题的一句话:

Random 类在生成唯一随机数序列的能力方面存在一些限制,请参阅文档的备注部分:

  1. 具体来说,因为 Random 的默认构造函数使用基于系统时钟的种子进行初始化,所以当 Random 实例的初始化非常快速地重复时,您可以获得重复的序列。前面引用的备注部分包含演示此问题的代码。
  2. 不保证对 Random 类实例的方法的调用是线程安全的。因此,使用 Random 的单个实例来避免种子问题可能会遇到其他线程问题。

使用Guid.NewGuid 方法对集合进行采样将为生成随机排序提供更好的结果,因为如果快速连续调用它不会重复序列。但是,它确实带有一些警告:

  1. 虽然它作为随机选择器在卡方测试中表现良好,但它不适合加密目的,也不能直接替代实际的随机数生成器。
  2. 只要 NewGuid 生成的 GUID 是版本 4 GUID,GUID 确实包含随机内容;但是,这可能会在未来发生变化。Microsoft 没有做出任何保证 GUID 将包含随机内容的声明,只是保证它们是唯一的,并且冲突概率极低。

这是使用 NewGuid 的样子:

string[] myRandomArray = choices.OrderBy(x => Guid.NewGuid()).Take(3).ToArray();

使用RNGCryptoServiceProvider 类是产生可靠随机抽样的最佳解决方案。它既是线程安全的,也不会受到 Random 类的种子问题的影响。然而,它确实需要更多的代码来实现。

// TODO: Add code to demonstrate using RNGCryptoServiceProvider

您可以使用 take 而不是 For 循环,因为您已经在使用 LINQ:

// Get 3 random choices in a List.
List<string> myChoices = choices.OrderBy(x => Guid.NewGuid()).Take(3).ToList();

// Add the correct answer.
myChoices.Add(theAnswer);

// Randomize the resulting set of 4 choices into an Array.
string[] myRandomizedChoices = myChoices.OrderBy(x => Guid.NewGuid()).ToArray();

this.radioButton1.Text = myRandomizedChoices[0];
this.radioButton2.Text = myRandomizedChoices[1];
this.radioButton3.Text = myRandomizedChoices[2];
this.radioButton4.Text = myRandomizedChoices[3];
于 2013-06-26T15:11:24.280 回答