c#如何防止从随机数算法填充重复数字?

时间:2017-11-30 21:44:46

标签: c# algorithm

我正在构建一个c#windows应用程序表单。 到目前为止,我已经生成了一个随机数算法,该算法用30(int)随机数填充列表框。 我没有使用数组,因为列表框本身就是一个数组。

我的问题是当我点击按钮生成30个随机数字时。这些数字已填充,但我有可能产生重复的数字,我希望防止这种情况发生。

我希望能够使用HashSet或Distinct方法来防止重复。我使用了一个简单的.Distinct来删除重复项,但它不会阻止重复项填充到列表中。

注意:我无法对列表框进行排序,因为我有单独的功能。

private void GenerateNumbers_Click(object sender, EventArgs e)
        {
            List<int> nums = new List<int>();
            Random rnd = new Random();
            //HashSet<int> duplicate = new HashSet<int>();
            //IEnumerable<int> RemoveDuplicates = numberList.Distinct();
            int produce;

            for (int i = 0; i < 30; i++)
            {
                produce = rnd.Next(1, 250);
                this.nums.Items.Insert(0, produce.ToString());
            }

            GenerateNumbers.Enabled = false; 
        }

3 个答案:

答案 0 :(得分:2)

所以你想要从1到250的30个数字?创建一个包含所有数字shuffle it的数组,然后取前30个。例如:

Random rand = new Random();

// create an array with 250 numbers, in order
var numbers = Enumerable.Range(1, 250).Select(x => x).ToArray();
// shuffle
for (int i = numbers.Length - 1; i > 0; --i)
{
    int n = rand.Next(i+1);
    int t = numbers[i];
    numbers[i] = numbers[n];
    numbers[n] = t;
}

// from here, just take the first 30 numbers

答案 1 :(得分:1)

我会选择一个枚举器:

    // will produce as many ints as needed (with duplicates).
    // do not call: YieldRandomInt(1,250).ToList();
    static IEnumerable<int> YieldRandomInt(int min, int max)
    {
        Random r = new Random();

        while (true)
            yield return r.Next(min, max);
    }

    // Gets as many distinct ints as needed and produces a list for you
    static IList<int> GetDistinctRandomInts(int count, int min, int max)
    {
        return YieldRandomInt(min, max).Distinct().Take(count).ToList();
    }

你的算法只需拨打var rnds = GetDistinctRandomInts(30,1,250);

洗牌方法也很好,为穷人(或富人?)洗牌:

Enumerable.Range(1, 250).OrderBy(r => Guid.NewGuid()).Take(30).ToList();

这将在每次调用时创建250个Guid并重新排序创建的范围 - 需要一些努力。它的随机性不是计算上/密码学上的声音 - 但是Random也不是。 (仍然:如果你多次打电话,请随机使用)

答案 2 :(得分:1)

稍微改变你的算法:

 private void GenerateNumbers_Click(object sender, EventArgs e)
        {
            List<int> nums = new List<int>(30);
            Random rnd = new Random();
            while (true)
            {
                int num = rnd.Next(1, 250);
                if (!nums.Contains(num))
                {
                    nums.Add(num);
                }
                if (nums.Count == 30)
                {
                    break;
                }                
            }
            // elided
        }

提案编辑:

    private void GenerateNumbers_Click(object sender, EventArgs e)
    {
        var nums = new HashSet<int>();
        Random rnd = new Random();

        while (nums.Count < 30)
            nums.Add(rnd.Next(1, 250));

        // use nums.ToList();
    }