随机数生成器,没有重复

时间:2014-11-14 13:51:16

标签: c#

基本上我正在创建一个程序来随机生成6个独特的彩票号码,因此在同一行中没有重复项,这是我到目前为止的代码......

        //Generate 6 random numbers using the randomiser object

        int randomNumber1 = random.Next(1, 49);
        int randomNumber2 = random.Next(1, 49);
        int randomNumber3 = random.Next(1, 49);
        int randomNumber4 = random.Next(1, 49);
        int randomNumber5 = random.Next(1, 49);
        int randomNumber6 = random.Next(1, 49);

        textBox1.Text = randomNumber1.ToString();
        textBox2.Text = randomNumber2.ToString();
        textBox3.Text = randomNumber3.ToString();
        textBox4.Text = randomNumber4.ToString();
        textBox5.Text = randomNumber5.ToString();
        textBox6.Text = randomNumber6.ToString();

    }

我收到的是随机数字,但有时在同一行上有相同的数字,我如何使每个数字唯一????

提前致谢

11 个答案:

答案 0 :(得分:29)

您需要将它们存储在一个集合中,每次选择一个新号码时,您需要确保它已经不存在,否则您需要生成一个新号码,直到找到一个唯一的号码。

而不是这个,我会在149之间生成一个序列,将它们混合并从序列中选出6个数字,例如:

var rnd = new Random();
var randomNumbers = Enumerable.Range(1,49).OrderBy(x => rnd.Next()).Take(6).ToList();

答案 1 :(得分:10)

你做不到。您只是指定每个数字是1到49之间的随机数,而不是它不应该与任何重复数字匹配。

由于你有一组相对较小的数字,你最好的选择可能是抽取随机数,将它们放入HashSet中,然后如果你需要更多数字,那就拉多了。像这样:

HashSet<int> numbers = new HashSet<int>();
while (numbers.Count < 6) {
    numbers.Add(random.Next(1, 49));
}

在这里,您可以利用HashSet消除重复项。这不适用于List或其他集合。

答案 2 :(得分:5)

返回重复值 是必需的,以便生成器满足随机性的必要统计属性:绘制数字的概率不依赖于先前绘制的数字。

您可以随机播放 1到49范围内的整数,并返回前6个元素。有关此类洗牌的更多详细信息,请参阅http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle

然而,我认为这样做会导致轻微的统计偏差。

最好的方法可能是使用random.Next(1, 49);并拒绝任何重复。这将不受统计偏差的影响,而且您只需要49个可能性中的6个,碰撞次数不会明显减慢算法。

答案 3 :(得分:3)

reservoir sampling使用此扩展方法:

public static IList<T> TakeRandom<T>(
    this IEnumerable<T> source, int count, Random random)
{
    var list = new List<T>(count);
    int n = 1;
    foreach (var item in source)
    {
        if (list.Count < count)
        {
            list.Add(item);
        }
        else
        {
            int j = random.Next(n);
            if (j < count)
            {
                list[j] = item;
            }
        }
        n++;
    }
    return list;
}

您可以像这样对您的收藏进行抽样:

var random = new Random();
var numbers = Enumerable.Range(1, 49).TakeRandom(6, random);
numbers.Shuffle(random);

请注意,返回的numbers将从{1,2,...,49}中的一组6个数字的所有(49选6)可能性中统一采样,但它们不会保留在订单也不一致洗牌。如果您想让订单随机化,您可以在之后轻松完成标准Fisher-Yates shuffle

public static void Shuffle<T>(this IList<T> list, Random random)
{
    for (int i = 0; i < list.Count; i++)
    {
        int j = random.Next(i, list.Count);
        T temp = list[j];
        list[j] = list[i];
        list[i] = temp;
    }
}
  

请注意,在这个答案中可以找到更加优化的Fisher-Yates shuffle版本:Randomize a List<T>

答案 4 :(得分:1)

   List<int> aux = new List<int>();
   while(aux.Count < 6)
   {
      int rnd = random.Next(1,49);
      if(!aux.Contains(rnd))aux.add(rnd);
   } 
  

如果您将所有Texbox放在同一个面板中,则可以执行此操作

  int j = 0;
  foreach(Control x in MyPanel.Controls)
  {
     if(x is TexBox)
     {
        x.Text = aux[j].toString();
        j++;
     } 
  } 

答案 5 :(得分:0)

使用array来保存您的6个号码。

每次生成一个,循环遍历数组以确保它不存在。如果是,那么生成另一个&amp;再次循环,直到你有一个不匹配。

答案 6 :(得分:0)

使用数组和OOP(面向对象编程)非常简单。在开始之前,您必须将 Linq(使用System.Linq)库添加到项目中。

Random random = new Random();
int[] array = new int[6];
int number;

for (int i = 0; i < 6; i++)
{
    number = random.Next(1, 50);
    if (!array.Contains(number)) //If it's not contains, add number to array;
    array[i] = number;
    else //If it contains, restart random process
    i--;
}

for (int i = 1; i < 7; i++)
{
    foreach (Control c in this.Controls) //Add random numbers to all Textboxes
    {
        if (c is TextBox && c.Name.EndsWith(i.ToString()))
        {
            c.Text = array[i - 1].ToString();
        }
    }
}

答案 7 :(得分:0)

功能方法可以是生成无限的随机数序列,过滤掉非唯一数字并获取所需的唯一数字。

例如:

private IEnumerable<int> RandomDigitStream(int seed)
{
    Random random = new Random(seed);
    while (true)
    {
        yield return random.Next(DIGIT_MIN, DIGIT_MAX);
    }
}

private List<int> GenerateUniqueRandomNumbers(int seed, int count)
{
     // Assert that DIGIT_MAX - DIGIT_MIN > count to ensure
     // algorithm can finish

     return RandomDigitStream(seed)
        .Distinct()
        .Take(count)
        .ToList();
}

此算法的效率主要取决于.NET团队如何实现Distinct。它的内存使用量会随着你需要的位数和随机函数产生的数字范围而增长。它还具有不可预测的运行时间,因为它取决于随机函数的概率分布。实际上,如果随机算法产生的数字范围小于您需要的位数,则该算法可能会陷入无限循环。

但实际上看,它对于少量数字应该没问题,但是如果你看一个大数字(100 +),你可能想看看其他方法。

如果在不使用查找表的情况下甚至可以生成一个只生成唯一数字的随机算法,效率会更高。

答案 8 :(得分:0)

为时已晚,但我使用了由我创建的名为M_Randomizer的方法。

using System;
class Randomizer
{
public int[] M_Randomizer(int x)
{
    bool b = false;
    if (x < -1)
    {
        b = true;
        x = -1 * x;
    }
    if(x == -1)
        x = 0;
    if (x < 2)
        return new int[x];

    int[] site;
    int k = new Random(Guid.NewGuid().GetHashCode()).Next() % 2;
    if (x == 2)
    {
        site = new int[2];
        site[0] = k;
        site[1] = 1 - site[0];
        return site;
    }
    else if (x == 3)
    {
        site = new int[3];
        site[0] = new Random(Guid.NewGuid().GetHashCode()).Next(0, 3);
        site[1] = (site[0] + k + 1) % 3;
        site[2] = 3 - (site[0] + site[1]);
        return site;
    }
    site = new int[x];
    int a = 0, m = 0, n = 0, tmp = 0;
    int[] p = M_Randomizer(3);
    int[] q;

    if (x % 3 == 0)
        q = M_Randomizer(x / 3);
    else
        q = M_Randomizer((x / 3) + 1);
    if (k == 0)
    {
        for (m = 0; m < q.Length; m++)
        {
            for (n = 0; n < p.Length && a < x; n++)
            {
                tmp = (q[m] * 3) + p[n];
                if (tmp < x)
                {
                    site[a] = tmp;
                    a++;
                }
            }
        }
    }
    else
    {
        while (n < p.Length)
        {
            while (a < x)
            {
                tmp = (q[m] * 3) + p[n];
                if (tmp < x)
                {
                    site[a] = tmp;
                    a++;
                }
                m = m + k;
                if (m >= q.Length)
                    break;
            }
            m = m % q.Length;
            n++;
        }
    }

    a = (new Random(Guid.NewGuid().GetHashCode()).Next() % 2) + 1;
    k = new Random(Guid.NewGuid().GetHashCode()).Next() % 10;
    if (k > 5)
        for (int i = a; i < k; i++)
            while (a < site.Length)
            {
                if (k % (a + 1) == 0)
                {
                    tmp = site[a - 1];
                    site[a - 1] = site[a];
                    site[a] = tmp;
                }
                a = a + 2;
            }

    k = new Random(Guid.NewGuid().GetHashCode()).Next() % 10;
    if (k > 5)
    {
        n = x / 2;
        k = 0;
        if (x % 2 != 0)
            k = (new Random(Guid.NewGuid().GetHashCode()).Next() % 2);

        p = new int[n + k];
        m = (x - n) - k;
        for (a = 0; m < x; a++, m++)
            p[a] = site[m];

        m = n + k;
        for (a = (x - m) - 1; a >= 0; a--, m++)
            site[m] = site[a];

        for (a = 0; a < p.Length; a++)
            site[a] = p[a];
    }

    int[] site2;
    int[] site3 = new int[x];
    if (b)
        return site;
    else
        site2 = M_Randomizer(-1 * x);

    for (a = 0; a < site.Length; a++)
        site3[site2[a]] = site[a];

    return site3;
}

public int[] M_Randomizer(int x, int start)
{
    int[] dm = M_Randomizer(x);

    for(int a = 0; a < x; a++)
        dm[a] = dm[a] + start;

    return dm;
}
}

答案 9 :(得分:0)

这是一个使用递归生成数字行的小程序,还使用递归来随机化并获得唯一的数字。

using System;
using System.Linq;
using System.Collections.Generic;

public class Program
{
    public static Random random;
    public static List<int> lottoNumbers = Enumerable.Range(1, 49).ToList();
    public static void Main()
    {
        random = new Random((int)DateTime.Now.Ticks);

        var LinesToGenerate = 10;

        GenerateNumbers(LinesToGenerate);
    }

    public static void GenerateNumbers(int LineCount)
    {
        int[] SelectedNumbers = new int[6];
        for (var i = 0; i < 6; i++)
        {
            var number = GetRandomNumber(lottoNumbers.ToArray());

            while (SelectedNumbers.Contains(number))
                number = GetRandomNumber(lottoNumbers.ToArray());

            SelectedNumbers[i] = number;
        }

        var numbersOrdered = SelectedNumbers.OrderBy(n => n).Select(n => n.ToString().PadLeft(2, '0'));
        Console.WriteLine(string.Join(" ", numbersOrdered));

        if (LineCount > 1)
            GenerateNumbers(--LineCount);
    }

    //Recursively and randomly removes numbers from the array until only one is left, and returns it
    public static int GetRandomNumber(int[] arr)
    {
        if (arr.Length > 1)
        {
            //Remove random number from array
            var r = random.Next(0, arr.Length);
            var list = arr.ToList();
            list.RemoveAt(r);
            return GetRandomNumber(list.ToArray());
        }

        return arr[0];
    }
}

答案 10 :(得分:-3)

是。使用数组。 循环你想要多少次: 生成一个随机数,     循环遍历数组并将所有数字与生成的数字进行比较 如果有匹配则再循环直到没有匹配。 然后存储它。

完成:)