非重复随机数

时间:2009-06-18 07:10:08

标签: c# random

要生成1-20的随机数,我需要选择性选择,不应该重复。

如何在C#中执行此操作

注意我需要像这样循环

Random rnd = new Random()
rnd.Next(1,20)
for(int i =0; i<=20;i++)
{

}

对于所有循环,数字应为1到20

10 个答案:

答案 0 :(得分:22)

你究竟是什么意思“不应该重复”?如果你的意思是你不想得到任何重复项,那么你应该基本上取一个数字1-20的列表,将它们洗牌,然后从头部一次抓一个名单。有关重新排列列表的有效方法,请参阅this Stack Overflow answer

如果你的意思是你当前的尝试给出5,5,5,5,5,5,1,1,1,1,1,1,1,1,2,2,2,2,2等那么每次你选择一个数字时,你很可能正在创建Random的新实例:不要这样做。每次创建实例时,它都会使用当前时间作为随机数生成器的“种子”(除非您明确指定一个)。这意味着如果您快速连续创建多个实例,每个实例将获得相同的种子,因此会给出相同的数字序列。

相反,请使用Random的单个实例并重复使用它。 (请注意,它不是线程安全的,这很痛苦。)例如:

private static readonly Random Rng = new Random();

public int NextNumber()
{
    return Rng.Next(20) + 1;
}

这不是线程安全的,但如果这是一个问题,请告诉我们。另一种方法是将Random传递给方法(当然,这通常会更复杂):

public int NextNumber(Random rng)
{
    return rng.Next(20) + 1;
}

然后调用者可以适当地重用该实例。

如果您想要一种生成随机数的线程安全方式,您可能需要查看StaticRandom中的MiscUtil课程。

(请注意,使用rng.Next(1, 21)也可以正常工作 - 我更喜欢上面的版本,因为我认为它可以减少对包容性/独占边界的猜测,但这是个人品味的问题。)

答案 1 :(得分:18)

此方法将生成所有数字,并且不会重复任何数字:

/// <summary>
/// Returns all numbers, between min and max inclusive, once in a random sequence.
/// </summary>
IEnumerable<int> UniqueRandom(int minInclusive, int maxInclusive)
{
    List<int> candidates = new List<int>();
    for (int i = minInclusive; i <= maxInclusive; i++)
    {
        candidates.Add(i);
    }
    Random rnd = new Random();
    while (candidates.Count > 0)
    {
        int index = rnd.Next(candidates.Count);
        yield return candidates[index];
        candidates.RemoveAt(index);
    }
}

你可以像这样使用它:

Console.WriteLine("All numbers between 0 and 20 in random order:");
foreach (int i in UniqueRandom(0, 20)) {
    Console.WriteLine(i);
}

答案 2 :(得分:2)

IEnumerable 实现,基于Hallgrim's回答:

public class UniqueRandoms : IEnumerable<int>
{
    Random _rand = new Random();
    List<int> _candidates;

    public UniqueRandoms(int maxInclusive)
        : this(1, maxInclusive)
    { }

    public UniqueRandoms(int minInclusive, int maxInclusive)
    {
        _candidates = 
            Enumerable.Range(minInclusive, maxInclusive - minInclusive + 1).ToList();
    }

    public IEnumerator<int> GetEnumerator()
    {
        while (_candidates.Count > 0)
        {
            int index = _rand.Next(_candidates.Count);
            yield return _candidates[index];
            _candidates.RemoveAt(index);
        }
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

答案 3 :(得分:1)

我这样做了一段时间。我不知道它与效率,随机性等方面的其他方法相比如何。但似乎有效:

List<int> integers = new List<int>() { 1, 2, 3, 4, 5, 6,7, 8, 9, 10, 11, 12 };

Random rnd = new Random();

var ints = from i in integers
           orderby rnd.Next(integers.Count)
           select i;

答案 4 :(得分:0)

来自MSDN

“改善随机性的一种方法是使种子值与时间有关。”

另一个事实

你应该“创建一个随机数来随时间生成许多随机数”。 这将增强随机生成

答案 5 :(得分:0)

class Program
{
    static void Main(string[] args)
    {        
        List<int> list = new List<int>();
        int val;
        Random r;
        int IntialCount = 1;
        int count = 7 ;
        int maxRandomValue = 8;

        while (IntialCount <= count)
        {
            r = new Random();
            val = r.Next(maxRandomValue);
            if (!list.Contains(val))
            {
                list.Add(val);
                IntialCount++;
            }

        } 
    }
}

答案 6 :(得分:0)

以下方式是非常好的方法,我在这里使用一个字符串,你可以将列表的类型改为你想要的任何东西......,试试吧:

            List<string> NamesList = new List<string>() { "Name1", "Name2", "Name3", "Name4", "Name5" };
            Random rnd = new Random();
            //Now to get random of the above "Without Repeating.."
            for (int i = 0; i <= NamesList.Count - 1; i++)
            {
                int TheSelectedRand = rnd.Next(NamesList.Count);
                string MyRandNumber = NamesList[TheSelectedRand];

                //Print or use your item here

                NamesList.Remove(NamesList[TheSelectedRand]);
            }

答案 7 :(得分:0)

就像我一样:

    list.Clear();
    int count = 0;
    
    while (count < 20)
    {            
        int x = Random.Range(1, 21);
        if (!list.Contains(x))
        {
            list.Add(x);
            count++;
        }
    }

答案 8 :(得分:-1)

打击代码在0到92之间生成65个唯一的随机数,并返回数组中的唯一随机数。

public static int[] RandomNumbers_Supplier()
        {
            Random R = new Random();
            int[] RandomNumbers = new int[65];
            int k = 0, Temp;
            bool IsRepetitive = false;
            while (k < 65)
            {
                Temp = R.Next(0, 92);
                for (int i = 0; i < 65; i++)
                {
                    IsRepetitive = false;
                    if (RandomNumbers[i] == Temp)
                    {
                        IsRepetitive = true;
                        break;
                    }                    
                }
                if (!IsRepetitive)
                {
                    RandomNumbers[k] = Temp;
                    k++;
                }
            }
            return(RandomNumbers)
        }

答案 9 :(得分:-1)

static void Main(string[] args)
{
    //Randomize 15 numbers out of 25 - from 1 to 25 - in ascending order
    var randomNumbers = new List<int>();
    var randomGenerator = new Random();
    int initialCount = 1;

    for (int i = 1; i <= 15; i++)
    {
        while (initialCount <= 15)
        {
            int num = randomGenerator.Next(1, 26);
            if (!randomNumbers.Contains(num))
            {
                randomNumbers.Add(num);
                initialCount++;
            }
        }
    }
    randomNumbers.Sort();
    randomNumbers.ForEach(x => Console.WriteLine(x));
}