3

I have 8 labels. I want each label to have its text property set to a random number. For some reason only the first label is having a number set, why is this? (Also, although not directly related, if there's a better way of doing label1.Text, label2.Text, label3.Text etc, please let me know!)

Thanks

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        go();
    }

    void go()
    {
        int[] numbers = new int[8];

        foreach (int number in numbers) 
        {
            numbers[number] = getRandomNumber();
        }

        label1.Text = numbers[0].ToString();
        label2.Text = numbers[1].ToString();
        label3.Text = numbers[2].ToString();
        label4.Text = numbers[3].ToString();
        label5.Text = numbers[4].ToString();
        label6.Text = numbers[5].ToString();
        label7.Text = numbers[6].ToString();
        label8.Text = numbers[7].ToString();
    }

    int getRandomNumber()
    {
        Random random = new Random();
        return random.Next(10, 1000);
    }
}
4

4 回答 4

6

编辑:更多问题

只有第一个标签有一个数字集

这样做的原因是您已经int[]以这种方式声明并初始化了 an:

int[] numbers = new int[8];

在此之后,您有一个包含Length8 的数组,但所有整数都是default(int)0。

因此以下foreach循环...

foreach (int number in numbers) 
{
    numbers[number] = getRandomNumber();
}

...只会将第一个初始化int为一个随机数(好吧,不是真正随机的,稍后会详细介绍)。您可以改用for-loop:

for (int iii=0; iii<numbers.Length;iii++)
{ 
    numbers[iii] = getRandomNumber();
}

但是,如果您使用下面我改进的代码,也可以解决这个问题。


在循环中使用相同的随机实例。否则它将创建相同的数字,因为它是用当前时间播种的。

MSDN

随机数生成从种子值开始。如果重复使用相同的种子,则会生成相同的数字序列。产生不同序列的一种方法是使种子值与时间相关,从而为每个新的 Random 实例产生不同的序列。默认情况下,Random 类的无参构造函数使用系统时钟生成其种子值,而其有参构造函数可以根据当前时间的刻度数取一个 Int32 值。

Random rnd = new Random();
foreach (int number in numbers) 
{
    numbers[number] = rnd.Next(10, 1000);
}

根据您的第二个问题如何改进代码:您可以使用带有标签的数组:

Random random = new Random();
var labels = new[] { label1, label2, label3, label4, label5, label6, label7, label8 };
for (int i = 0; i < labels.Length; i++)
{
    labels[i].Text = random.Next(10, 1000).ToString();
}
于 2013-08-06T22:12:16.717 回答
5

问题出在你的foreach循环中。number当它实际上是数组中索引处的值时,您将其用作索引。效果是只有第一个label.Text才会有值!Random此外,由于您每次都创建一个新的,Random.Next因此将返回相同的值,因为随机种子是基于时间的。试试这个:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        go();
    }

    void go()
    {
        int[] numbers = new int[8];

        Random random = new Random();

        for (int i = 0; i < 8; i++)
        {
            numbers[i] = random.Next(10, 1000);
        }

        label1.Text = numbers[0].ToString();
        label2.Text = numbers[1].ToString();
        label3.Text = numbers[2].ToString();
        label4.Text = numbers[3].ToString();
        label5.Text = numbers[4].ToString();
        label6.Text = numbers[5].ToString();
        label7.Text = numbers[6].ToString();
        label8.Text = numbers[7].ToString();
    }
}
于 2013-08-06T22:15:55.967 回答
1

这是因为

int getRandomNumber()
{
    Random random = new Random(); // <-- This line
    return random.Next(10, 1000);
}

改为这样做:

private static readonly Random random = new Random(); // <-- only set once

int getRandomNumber()
{
    return random.Next(10, 1000);
}

第一个中发生的情况是,您一遍又一遍地用相同的值播种它,因为如果循环太紧,从技术上讲时间还没有滴答作响。在第二个中,我正在做的是给生成器播种一次——因此每次都会得到不同的数字。

于 2013-08-06T22:11:51.507 回答
0

正如ShadowCat7所指出的,这里的核心问题不是Random被滥用,而是foreach循环被滥用。

以下代码行。

int[] numbers = new int[8];

int在 的值处声明一个 8 的数组0

因此,当您执行以下foreach循环时。

foreach (int number in numbers) 
{
    numbers[number] = getRandomNumber();
}

您正在遍历int整数数组中包含的每个值numbers,如前所述,它们都是0!因此,当您将它用作数组索引运算符 [] 中的参数时,您会重复进行此调用。

numbers[0] = getRandomNumber();

这就是为什么您没有看到数组的其余部分填充了 10 到 1000 之间的伪随机数的真正原因。

虽然不断创建一个新的实例确实Random会通过重复使用相同的种子一次又一次地为你生成相同的数字(违背了Random在这样的循环中使用的目的),但这里的主要问题是为什么你的 8 个中有 7 个标签0是因为foreach循环的误用。

至于为Text每个设置值的巧妙方法Label,请参阅Tim Schmelter的答案,因为它很棒。

于 2013-08-06T23:56:19.203 回答