【发布时间】:2011-07-26 11:25:18
【问题描述】:
用户在 10 文本框中输入数字,我将它们发送到一个数组。现在我想从这个数组中生成随机数。我能做什么?
【问题讨论】:
-
你想从数组中选择随机数吗?还是将数组用作随机数生成器的“种子”?
-
然后看看我的回答(如果它解决了你的问题,请接受它)。
-
等等...所以你想洗牌阵列,而不是播种 PRNG?
用户在 10 文本框中输入数字,我将它们发送到一个数组。现在我想从这个数组中生成随机数。我能做什么?
【问题讨论】:
类似这样的:
public class Randomizer<T>
{
private readonly Random _random = new Random();
private readonly IList<T> _numbers;
public Randomizer(IList<T> numbers)
{
_numbers = numbers;
}
public T Next()
{
int idx = _random.Next(0, _numbers.Count);
return _numbers[idx];
}
}
用法:
var r = new Randomizer<int>(new int[] { 10, 20, 30, 40, 50 });
for (int i = 0; i < 100; i++)
Console.Write(r.Next() + " ");
或者你想shuffle the array?
[编辑]
要打乱数组,可以使用this post中显示的Fisher–Yates shuffle:
// https://stackoverflow.com/questions/108819/110570#110570
public class Shuffler
{
private Random rnd = new Random();
public void Shuffle<T>(IList<T> array)
{
int n = array.Count;
while (n > 1)
{
int k = rnd.Next(n);
n--;
T temp = array[n];
array[n] = array[k];
array[k] = temp;
}
}
}
如果你想让接口和上面的Randomizer类一样,可以修改为使用Shuffler类:
public class Randomizer<T>
{
private readonly Shuffler _shuffler = new Shuffler();
private readonly IList<T> _numbers;
public Randomizer(IList<T> numbers)
{
_numbers = new List<T>(numbers);
_shuffler.Shuffle(_numbers);
}
volatile int idx = 0;
public T Next()
{
if (idx >= _numbers.Count)
{
_shuffler.Shuffle(_numbers);
idx = 0;
}
return _numbers[idx++];
}
}
请注意,代码不是线程安全的,因此如果可能从多个线程同时调用Next 方法,则应实施一些锁定。
【讨论】:
Seed 标准的System.Random 类具有来自数组的值?如果您需要随机数依赖于所有数组项,那么只需对它们进行异或。
public static Random BuildSeededRandom(int[] data)
{
if ( data == null || data.Length < 1 )
return new Random();
int xor = 0;
foreach ( var i in data )
xor ^= i;
return new Random(xor);
}
【讨论】: