生成随机的唯一值 C#
本文关键字:唯一 随机 | 更新日期: 2023-09-27 17:55:11
我已经搜索了一段时间,一直在努力找到这个,我正在尝试生成几个随机的唯一数字是 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
更好的方法吗?谢谢<</p>
我定期调用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);
}
如果您的范围只有 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]);
注意,我不推荐这个:)。这也是一个"单行":
var result = Enumerable.Range(0,9).OrderBy(g => Guid.NewGuid()).ToArray();
我发布了随机算法的正确实现,因为此处发布的另一个算法不会产生统一的随机播放。
正如另一个答案所述,对于要随机化的少量值,您可以简单地用这些值填充数组,打乱数组,然后使用您想要的任意数量的值。
以下是 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;
}
}
这是一个唯一的统一答案:
检查这个即用型方法:给出你想要得到的数字的范围和数量。
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;
}
与@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 设为静态。
根据你真正想要的东西,你可以做这样的事情:
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;
}
}
}
这是我使用 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();
}
}
}
注意到接受的答案不断将 int 添加到列表中,并不断用if (!randomList.Contains(MyNumber))
检查它们,我认为这不能很好地扩展,特别是如果您不断要求新数字。
我会反其道而行之。
- 在启动时线性生成列表
- 从列表中获取随机索引
- 从列表中删除找到的 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;
}
}
}
可能有点晚了,但这里有更合适的代码,例如当你需要使用循环时:
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];
}
- 带功能方式*
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;
}
Random r = new Random(); int[] v = new int[10];
for (int i = 0; i < 10; i++)
{
v[i] = r.Next(1, 25); // random numbers between (1) and (25)
for (int j = 0; j < i; j++)
{
if (v[j] == v[i]) // if it is a duplicated value, create new one!
i--;
}
}
for (int i = 0; i < 10; i++)
textBox1.Text += v[i].ToString() + " ";
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;
}
}
你也可以使用一个存储每个随机值的 dataTable,然后简单地执行随机方法,而 != dataColumn
randomNumber 函数返回 0 到 100000 之间的 unqiue 整数值
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; }
我在这里发布了一个视频,它解释了如何生成唯一的随机数
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 个数字)开始的非重复数字作为随机.. 谢谢......
您可以使用 C# 的基本随机函数
Random ran = new Random();
int randomno = ran.Next(0,100);
您现在可以在您想要的任何内容中使用 randomno 中的值,但请记住,这将生成一个介于 0
和 100
Only 之间的随机数,您可以将其扩展到任何数字。
试试这个:
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
,但哈希码并不相同。