36

我已经搜索了一段时间并且一直在努力找到这个,我正在尝试生成几个随机的、唯一的数字是 C#。我正在使用System.Random,并且我正在使用DateTime.Now.Ticks种子:

public Random a = new Random(DateTime.Now.Ticks.GetHashCode());
private void NewNumber()
{
    MyNumber = a.Next(0, 10);
}

NewNumber()经常打电话,但问题是我经常收到重复的号码。有人建议,因为我每次都声明随机数,它不会产生随机数,所以我把声明放在我的函数之外。有什么建议或比使用更好的方法System.Random吗?谢谢

4

17 回答 17

27

我经常打电话给 NewNumber(),但问题是我经常得到重复的数字。

Random.Next不保证数字是唯一的。此外,您的范围是从 0 到 10,您可能会得到重复的值。可能是您可以int在检查它是否不包含重复项后设置一个列表并在列表中插入随机数。就像是:

public Random a = new Random(); // replace from new Random(DateTime.Now.Ticks.GetHashCode());
                                // Since similar code is done in default constructor internally
public List<int> randomList = new List<int>();
int MyNumber = 0;
private void NewNumber()
{
    MyNumber = a.Next(0, 10);
    if (!randomList.Contains(MyNumber))
        randomList.Add(MyNumber);
}
于 2013-01-23T05:58:36.630 回答
21

如果您的范围仅为 0 到 9,您可以尝试对可能的整数数组进行改组。这增加了避免数字生成中任何冲突的好处。

var nums = Enumerable.Range(0, 10).ToArray();
var rnd = new Random();

// Shuffle the array
for (int i = 0;i < nums.Length;++i)
{
    int randomIndex = rnd.Next(nums.Length);
    int temp = nums[randomIndex];
    nums[randomIndex] = nums[i];
    nums[i] = temp;
}

// Now your array is randomized and you can simply print them in order
for (int i = 0;i < nums.Length;++i)
    Console.WriteLine(nums[i]);
于 2013-01-23T06:03:52.523 回答
13

注意,我不推荐这个:)。 这里还有一个“oneliner”:

var result = Enumerable.Range(0,9).OrderBy(g => Guid.NewGuid()).ToArray();
于 2016-01-11T08:01:42.297 回答
10

我发布了一个正确的洗牌算法实现,因为这里发布的另一个不会产生统一的洗牌。

正如另一个答案所述,对于要随机化的少量值,您可以简单地用这些值填充一个数组,对数组进行洗牌,然后使用您想要的任意数量的值。

以下是Fisher-Yates Shuffle(又名 Knuth Shuffle)的实现。(阅读该链接的“实现错误”部分(搜索“在每次迭代时始终从有效数组索引的整个范围中选择 j”)以查看有关此处发布的其他实现有什么问题的一些讨论。)

using System;
using System.Collections.Generic;

namespace ConsoleApplication2
{
    static class Program
    {
        static void Main(string[] args)
        {
            Shuffler shuffler = new Shuffler();
            List<int> list = new List<int>{ 1, 2, 3, 4, 5, 6, 7, 8, 9 };
            shuffler.Shuffle(list);

            foreach (int value in list)
            {
                Console.WriteLine(value);
            }
        }
    }

    /// <summary>Used to shuffle collections.</summary>

    public class Shuffler
    {
        public Shuffler()
        {
            _rng = new Random();
        }

        /// <summary>Shuffles the specified array.</summary>
        /// <typeparam name="T">The type of the array elements.</typeparam>
        /// <param name="array">The array to shuffle.</param>

        public void Shuffle<T>(IList<T> array)
        {
            for (int n = array.Count; n > 1; )
            {
                int k = _rng.Next(n);
                --n;
                T temp = array[n];
                array[n] = array[k];
                array[k] = temp;
            }
        }

        private System.Random _rng;
    }
}
于 2013-01-23T09:06:43.403 回答
4

这是一个统一的答案:

检查这个现成的方法:给出你想要获得的数字的范围和数量。

public static int[] getUniqueRandomArray(int min, int max, int count) {
    int[] result = new int[count];
    List<int> numbersInOrder = new List<int>();
    for (var x = min; x < max; x++) {
        numbersInOrder.Add(x);
    }
    for (var x = 0; x < count; x++) {
        var randomIndex = UnityEngine.Random.Range(0, numbersInOrder.Count);
        result[x] = numbersInOrder[randomIndex];
        numbersInOrder.RemoveAt(randomIndex);
    }

    return result;
}
于 2017-11-21T19:13:30.523 回答
3

@Habib 的答案相同,但作为一个函数:

List<int> randomList = new List<int>();
int UniqueRandomInt(int min, int max)
{
    var rand = new Random();
    int myNumber;
    do
    {
       myNumber = rand.Next(min, max);
    } while (randomList.Contains(myNumber));
    return myNumber;
}

如果 randomList 是一个类属性,UniqueRandomInt 将在该类的同一实例的上下文中返回唯一整数。如果您希望它在全球范围内是唯一的,则需要将 randomList 设为静态。

于 2020-08-26T21:01:53.893 回答
2

根据您的实际情况,您可以执行以下操作:

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

namespace SO14473321
{
    class Program
    {
        static void Main()
        {
            UniqueRandom u = new UniqueRandom(Enumerable.Range(1,10));
            for (int i = 0; i < 10; i++)
            {
                Console.Write("{0} ",u.Next());
            }
        }
    }

    class UniqueRandom
    {
        private readonly List<int> _currentList;
        private readonly Random _random = new Random();

        public UniqueRandom(IEnumerable<int> seed)
        {
            _currentList = new List<int>(seed);
        }

        public int Next()
        {
            if (_currentList.Count == 0)
            {
                throw new ApplicationException("No more numbers");
            }

            int i = _random.Next(_currentList.Count);
            int result = _currentList[i];
            _currentList.RemoveAt(i);
            return result;
        }
    }
}
于 2013-01-23T06:42:20.783 回答
1

在这里,我使用HashSet查找 N 个随机唯一数字的版本。看起来很简单,因为 HashSet 只能包含不同的项目。很有趣 - 会比使用 List 或 Shuffler 更快吗?

using System;
using System.Collections.Generic;

namespace ConsoleApplication1
{
    class RnDHash
    {
        static void Main()
        {
            HashSet<int> rndIndexes = new HashSet<int>();
            Random rng = new Random();
            int maxNumber;
            Console.Write("Please input Max number: ");
            maxNumber = int.Parse(Console.ReadLine());
            int iter = 0;
            while (rndIndexes.Count != maxNumber)
            {
                int index = rng.Next(maxNumber);
                rndIndexes.Add(index);
                iter++;
            }
            Console.WriteLine("Random numbers were found in {0} iterations: ", iter);
            foreach (int num in rndIndexes)
            {
                Console.WriteLine(num);
            }
            Console.ReadKey();
        }
    }
}
于 2017-01-29T13:03:55.577 回答
1

我注意到接受的答案不断将 int 添加到列表中并不断检查它们,if (!randomList.Contains(MyNumber))我认为这不能很好地扩展,特别是如果你一直要求新的数字。

我会做相反的事情。

  1. 启动时线性生成列表
  2. 从列表中获取随机索引
  3. 从列表中删除找到的 int

这将需要在启动时稍微多一点时间,但会更好地扩展。

public class RandomIntGenerator
{
    public Random a = new Random();
    private List<int> _validNumbers;

    private RandomIntGenerator(int desiredAmount, int start = 0)
    {
        _validNumbers = new List<int>();
        for (int i = 0; i < desiredAmount; i++)
            _validNumbers.Add(i + start);
    }

    private int GetRandomInt()
    {
        if (_validNumbers.Count == 0)
        {
            //you could throw an exception here
            return -1;
        }
        else
        {
            var nextIndex = a.Next(0, _validNumbers.Count - 1);
            var number    = _validNumbers[nextIndex];
            _validNumbers.RemoveAt(nextIndex);
            return number;
        }
    }
}
于 2019-07-09T09:40:19.877 回答
0

可能有点晚了,但这里有更合适的代码,例如当您需要使用循环时:

            List<int> genered = new List<int>();

            Random rnd = new Random();

            for(int x = 0; x < files.Length; x++)
            {
                int value = rnd.Next(0, files.Length - 1);
                while (genered.Contains(value))
                {
                    value = rnd.Next(0, files.Length - 1);
                }
                genered.Add(value);

                returnFiles[x] = files[value];
            }
于 2020-01-24T11:00:54.633 回答
0
  • 功能方式*
        static Func<int> GetNextUniqueIntegerFunc(int min, int max)
        {
            var list = new List<int>();

            var random = new Random();

            int getNextValue()
            {
                while (true)
                {
                    var random_number = random.Next(min, max);

                    if (!list.Contains(random_number))
                    {
                        list.Add(random_number);

                        return random_number;
                    }
                }
            }

            return getNextValue;
        }
于 2021-12-07T22:21:20.647 回答
-1

从 0 到 9 的唯一随机数

      int sum = 0;
        int[] hue = new int[10];
        for (int i = 0; i < 10; i++)
        {

            int m;
            do
            {
                m = rand.Next(0, 10);
            } while (hue.Contains(m) && sum != 45);
            if (!hue.Contains(m))
            {
                hue[i] = m;
                sum = sum + m;
            }

        }
于 2020-07-03T14:12:58.640 回答
-2

randomNumber 函数返回 0 到 100000 之间的唯一整数值

  bool check[] = new bool[100001];
  Random r = new Random();
  public int randomNumber() {
      int num = r.Next(0,100000);
       while(check[num] == true) {
             num = r.Next(0,100000);
     }
    check[num] = true;
   return num;
 }
于 2018-12-27T15:24:09.557 回答
-3

您还可以使用 dataTable 存储每个随机值,然后简单地执行 random 方法 while != dataColumn 中的值

于 2013-04-24T06:56:37.433 回答
-3

嗨,我在这里发布了一个视频,它解释了如何生成唯一的随机数

  public List<int> random_generator(){

  Random random = new Random();

   List<int> random_container = new List<int>;

     do{

       int random_number = random.next(10);

      if(!random_container.contains(random_number){

       random_container.add(random_number)
  }
}
   while(random_container.count!=10);


     return random_container; 
  }

在这里,,,在随机容器中,您将随机获得从 0 到 9(10 个数字)开始的非重复 10 个数字.. 谢谢........

于 2019-04-07T13:03:35.300 回答
-4

您可以使用 C# 的基本随机函数

Random ran = new Random();
int randomno = ran.Next(0,100);

你现在可以在任何你想要的东西中使用 randomno 中的值,但请记住,这将在0100Only 之间生成一个随机数,你可以将它扩展到任何数字。

于 2017-07-19T09:41:38.433 回答
-8

试试这个:

private void NewNumber()
  {
     Random a = new Random(Guid.newGuid().GetHashCode());
     MyNumber = a.Next(0, 10);
  }

一些解释:

Guid:基于此处: 表示全局唯一标识符 (GUID)

Guid.newGuid()产生一个唯一标识符,如"936DA01F-9ABD-4d9d-80C7-02AF85C822A8"

它将在整个宇宙中独一无二

这里的哈希码从我们的唯一标识符中产生一个唯一的整数

所以Guid.newGuid().GetHashCode() 给了我们一个唯一的数字,随机类将产生真正的随机数抛出这个

示例: https ://rextester.com/ODOXS63244

使用这种方法生成了十个随机数,结果为:

-1541116401
7
-1936409663
3
-804754459
8
1403945863
3
1287118327
1
2112146189
1
1461188435
9
-752742620
4
-175247185
4
1666734552
7

我们有两个1相邻的 s,但哈希码不一样。

于 2016-02-23T15:35:19.560 回答