选择唯一的随机数

时间:2016-01-31 22:41:25

标签: .net vb.net random

我试图在VB.NET中随机化一个数字3次。每次我随机化一个数字时,它应该与其他两个数字不同。

例如,我有3个整数。 Int1,Int2和Int3。我会在1-10之间随机化Int1,然后我会在1-10之间随机化Int2,但是这个值不应该等于我在Int1中随机化的值,而Int3也是如此,它不应该等于Int1和Int2。

我已经想出如何随机化一个数字,这是我使用的代码:

Dim RndNumber As Random
Dim num,num2 As Integer
RndNumber = New Random
num = RndNumber.Next(1, 11)
num2 = RndNumber.Next(1, 11)

现在我仍然坚持如何让num2随机化1-10之间的数字,这不等于num。

感谢任何帮助,谢谢。

1 个答案:

答案 0 :(得分:9)

在所有示例中,RNG是从NET Random类创建的随机数生成器:

Private RNG = New Random()

LINQ的

如果您只需要两个或三个,则可以循环,直到当前选择不在结果集中。但是使用一些扩展方法更简单:

Dim nums = Enumerable.Range(1, 10).
                OrderBy(Function(r) RNG.Next).
                Take(3).
                ToArray()

这从1到10之间的所有数字开始,按随机顺序排列,取前3个并将它们存储在nums数组中。我使用多线形式,在.之后断开以说明步骤。

只需根据需要更改范围,大小/数量和Take()元素。例如,对于像5号独特数字(浓缩形式)的彩票这样的东西:

Dim winners = Enumerable.Range(1, 69).OrderBy(Function(r) RNG.Next()).Take(5).ToArray()
Dim powerball = Enumerable.Range(1, 26).OrderBy(Function(r) RNG.Next()).Take(1).First

由于Powerball 可以重复第一个数字,因此它来自自己的池。由于我们只想要一个,我们不需要一个数组,只需要First()

手册

了解这些内容的逻辑是很好的,因此这显示了手动版本。通过选择并实际检查随机值,这会有所不同:

' picked value storage
Dim picks As New List(Of Int32)

Dim pick As Int32          ' current candidate
Do
    pick = RNG.Next(1, 11)
    If picks.Contains(pick) = False Then
        picks.Add(pick)
    End If
Loop Until picks.Count = 3

这不是松散的变量,而是使用一个列表来保存选择。这样可以轻松查看当前选择是否已被选中。如果不仅仅是几个值,请使用HashSet(Of Int32)而不是列表来提高性能。

随机对

要创建一个随机的数字,每个数字为2,例如匹配游戏,只需将基础值加倍,然后按随机顺序排列:

' create pool of 2 values each for 1-13
Dim nums = Enumerable.Range(1, 13).ToArray()
' concat the set to make 2 of each value, randomize 
Dim pool = nums.Concat(nums).OrderBy(Function(r) RNG.Next).ToArray()

对于手动方法,您必须检查循环中每个值的计数。

'用完了'精选

另外一个变体是当你需要定期使用一组randoms,但你不知道你需要提前多少。例如BINGO游戏或一副牌的球。

Stack(Of T)(或Queue)将使用"用尽#34;你需要的价值观:

' create, randomize pool of 100 ints
Dim nums = Enumerable.Range(1, 100).OrderBy(Function(r) RNG.Next).ToArray
' use array to create Stack<T>
Dim shoe As New Stack(Of Int32)(nums)

' same as:
Dim shoe = New Stack(Of Int32)(Enumerable.Range(1, 100).
                                OrderBy(Function(r) RNG.Next).ToArray())

这与100个整数基本相同,随机化并存储在数组中,但没有Take(n),因为我们想要它们全部。然后将它们的值存储在堆栈集合中。使用它:

Console.WriteLine(shoe.Count)
For n As Int32 = 1 To 3
    Console.WriteLine("Picked #{0}", shoe.Pop)
Next
Console.WriteLine(shoe.Count)

当您Pop一个值时,它会自动从集合中删除。如果您使用鞋子中的很多值,您将需要检查计数以确保它不是空的。

  

100
  挑选#12
  挑选了#69
  挑选了#53
  97

在绘制3个值后,鞋子只剩下97个值。

随机笔记

在所有情况下,您的Random生成器应该是您创建一次的表单级对象。永远不要在循环中创建它们,否则你可能会一遍又一遍地获得相同的值。

OrderBy(Function(r) RNG.Next)随机化方法通常足以供临时使用,但效率低下。如果您要随机化大型集合和/或经常使用它,您应该考虑使用适当的随机播放,例如the Fisher-Yates shuffle shown here