2010-05-13 3 views
3

Я пытаюсь создать лотерейный симулятор. Лотерея имеет 6 номеров, число сгенерированных должно быть от 1 до 49 и не может быть в следующем количестве сгенерировано. Я попытался использовать функцию ИЛИ, но я не совсем уверен, правильно ли я использую ее. Любая помощь будет большой. Благодарю.VB.NET - Удаление номера из генератора случайных чисел

Public Class Form1 

Private Sub cmdRun_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdRun.Click 
    ''#Creates a new Random class in VB.NET 
    Dim RandomClass As New Random() 



    ''#################################### 
    Dim RandomNumber1 As Integer 
    RandomNumber1 = RandomClass.Next(1, 49) 
    ''#Displays first number generated 
    txtFirst.Text = (RandomNumber1) 



    ''#################################### 
    Dim RandomNumber2 As Integer 
    RandomNumber2 = RandomClass.Next(1, 49) 
    If RandomNumber2 = RandomNumber1 Then 
     RandomNumber2 = RandomClass.Next(1, 49) 
    End If 

    ''#Displays second number generated 
    txtSecond.Text = (RandomNumber2) 



    ''#################################### 
    Dim RandomNumber3 As Integer 
    RandomNumber3 = RandomClass.Next(1, 49) 
    If RandomNumber3 = RandomNumber2 Or RandomNumber2 Then 
     RandomNumber3 = RandomClass.Next(1, 49) 
    End If 

    ''#Displays third number generated 
    txtThird.Text = (RandomNumber3) 



    ''#################################### 
    Dim RandomNumber4 As Integer 
    RandomNumber4 = RandomClass.Next(1, 49) 
    If RandomNumber4 = RandomNumber3 Or RandomNumber2 Or RandomNumber1 Then 
     RandomNumber4 = RandomClass.Next(1, 49) 
    End If 

    ''#Displays fourth number generated 
    txtFourth.Text = (RandomNumber4) 



    ''#################################### 
    Dim RandomNumber5 As Integer 
    RandomNumber5 = RandomClass.Next(1, 49) 
    If RandomNumber5 = RandomNumber4 Or RandomNumber3 Or RandomNumber2 Or RandomNumber1 Then 
     RandomNumber5 = RandomClass.Next(1, 49) 
    End If 

    ''#Displays fifth number generated 
    txtFifth.Text = (RandomNumber5) 



    ''#################################### 
    Dim RandomNumber6 As Integer 
    RandomNumber6 = RandomClass.Next(1, 49) 
    If RandomNumber6 = RandomNumber5, RandomNumber4, RandomNumber3, RandomNumber2, RandomNumber1 Then 
     RandomNumber6 = RandomClass.Next(1, 49) 
    End If 

    ''#Displays sixth number generated 
    txtSixth.Text = (RandomNumber6) 


End Sub 
+1

Обратите внимание, что 'Next (1, 49)' не возвращает случайное число в диапазоне 1-49, но в диапазоне 1-48. – Guffa

ответ

5

Вместо «Если», использование «Пока» - другими словами, держать генерации случайных чисел до тех пор, пока не найдете новую. В настоящее время, если вы получаете дубликат, а затем получаете дубликат во второй попытке, вы будете продолжать.

Кроме того, в то время как я не эксперт VB, я полагаю, вам нужно указать каждое сравнение в полном объеме, так что вместо этого:

If RandomNumber3 = RandomNumber2 Or RandomNumber2 Then 
    RandomNumber3 = RandomClass.Next(1, 49) 
End If 

вам нужно:

While RandomNumber3 = RandomNumber1 Or RandomNumber3 = RandomNumber2 Then 
    RandomNumber3 = RandomClass.Next(1, 49) 
End While 

Там альтернативы здесь - например, генерирование чисел 1-49, перетасовка их, а затем получение первых 6 результатов ... или сохранение «выбор до новой», но сохранение результатов в наборе. В любом случае вы можете избежать дублирования кода.

+1

Определенно переходите к тасованию - подумайте, что это больше похоже на колоду карт. Не совсем точно, как обычно работают лотереи, но математически результат должен быть точно таким же. –

+0

На самом деле именно так работают лотереи (дисконтирование P в PRNG). Как только число выбрано (1-из-49), это число имеет нулевую вероятность повторного выбора, а шансы любого другого конкретного номера теперь составляют 1-в-48. Перетасовка делает это. – paxdiablo

+0

@ pax-- Я знаю ... Я просто имею в виду, что с шарами пинг-понга вы берете один, затем перетасовываете остальные, затем берете другое и так далее. Это процедурный. С этим вы просто перетасовываете один раз (больше было бы в порядке, но не нужно), и у вас есть все номера сразу –

3

Здесь вам не нужен генератор случайных чисел, вам нужен один в сочетании с алгоритмом перетасовки.

Создание массива N элементов (мы будем использовать семь для нашего примера), каждый из которых содержит целое число, относящееся к его положению:

+---+---+---+---+---+---+---+ 
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 
+---+---+---+---+---+---+---+ 
          <pool(7) 

и установить размер пула до 7.

Тогда генерируйте свое случайное число, исходя из размера пула (т. е. получите число от 1 до 7). Допустим, что ваш генератор возвращает 3.

Вытащить значение в положении 3 затем заменить, что с верхним значением, затем уменьшить размер пула:

+---+---+---+---+---+---+---+ 
| 1 | 2 | 7 | 4 | 5 | 6 | 7 | -> 3 
+---+---+---+---+---+---+---+ 
         <pool(6) 

Тогда вы просто продолжать делать это до тех пор, пока вы получили количество требуемых значений. Если наше лото было 5 из 7:

+---+---+---+---+---+---+---+ 
| 1 | 2 | 7 | 4 | 5 | 6 | 7 | 
+---+---+---+---+---+---+---+ 
          <pool(7) 
rnd(7) returns 3 
+---+---+---+---+---+---+---+ 
| 1 | 2 | 7 | 4 | 5 | 6 | 7 | -> 3 
+---+---+---+---+---+---+---+ 
         <pool(6) 
rnd(6) returns 1 
+---+---+---+---+---+---+---+ 
| 6 | 2 | 7 | 4 | 5 | 6 | 7 | -> 1 
+---+---+---+---+---+---+---+ 
        <pool(5) 
rnd(5) returns 5 
+---+---+---+---+---+---+---+ 
| 6 | 2 | 7 | 4 | 5 | 6 | 7 | -> 5 
+---+---+---+---+---+---+---+ 
       <pool(4) 
rnd(4) returns 2 
+---+---+---+---+---+---+---+ 
| 6 | 4 | 7 | 4 | 5 | 6 | 7 | -> 2 
+---+---+---+---+---+---+---+ 
      <pool(3) 
rnd(3) returns 1 
+---+---+---+---+---+---+---+ 
| 7 | 4 | 7 | 4 | 5 | 6 | 7 | -> 6 
+---+---+---+---+---+---+---+ 
     <pool(2) 

и там вы имеете его, 5-от-7 чисел (3,1,5,2,6), экстрагированных без каких-либо возможностей дублей и эффективного О (п) метод их получения. Любое решение, которое полагается только на получение случайных чисел и проверку, если они уже были использованы, будет менее эффективным.

+1

Я не думаю, что вам нужно перетасовать цифры, если вы планируете случайно выбрать один для удаления. Чувствует себя немного как пояс с подтяжками, он будет работать, но немного лишний. – R0MANARMY

+0

Перемешивание необходимо для обеспечения того, чтобы дополнительный выбор выполнялся с помощью операции O (1). Если вы не перетасовываете, а rnd (7) возвращает 6 дважды, это ничем не отличается от необходимости хранить список ранее использованных номеров для проверки. Перетасовка гарантирует, что выбор одного и того же номера дважды невозможно, но при этом нужно только один раз вызвать rnd(). Это лучший способ использовать использованные номера из пула. – paxdiablo

+1

Возможно, вы страдаете от недоразумения, что перетасовка означает много свопов. Перемешивание в этом случае просто перемещает верхний элемент в тот, который вы только что извлекли, и уменьшите размер пула. Это означает, что вы можете реализовать его с помощью простого быстрого массива вместо типа коллекции. – paxdiablo

0

я бы что-то вроде (в C#)

public static IEnumerable<int> Lotto(int max) 
    { 
     var random = new Random((int)DateTime.Now.Ticks); 
     var numbers = new List<int>(Enumerable.Range(1, max)); 
     while(numbers.Count > 0) 
     { 
      int index = random.Next(1, numbers.Count) - 1; 
      yield return numbers[index]; 
      numbers.RemoveAt(index); 
     } 
    } 

    static void Main(string[] args) 
    { 


     var lotto = Lotto(49).GetEnumerator(); 
     lotto.MoveNext(); 
     int r1 = lotto.Current; 
     lotto.MoveNext(); 
     int r2 = lotto.Current; 
     lotto.MoveNext(); 
     int r3 = lotto.Current; 

     Console.WriteLine("{0} {1} {2}", r1, r2, r3); 

    } 
0

Вместо того, чтобы выбрать случайные числа и проверку дубликатов, вы можете просто перебрать цифры и проверить шансы для каждого номера ковыряться против случайное число:

Dim count As Integer = 6 ' How many numbers to pick 
Dim pos As Integer = 1 ' Lowest value to pick from 
Dim items As Integer = 49 ' Number of items in the range 

Dim rnd As New Random() 
Dim result As New List(Of Integer)() 

While count > 0 
    If rnd.Next(items) < count Then 
    result.Add(pos) 
    count -= 1 
    End If 
    pos += 1 
    items -= 1 
End While 

в списке result теперь содержит шесть чисел без дубликатов, произвольно выбранных из диапазона 1-49. В качестве дополнительного бонуса номера в списке уже отсортированы.

1

Вот еще один вариант, с помощью LINQ, если у вас есть VB2008:

Dim rnd As New Random() 

Dim randomNumbers = From n in Enumerable.Range(1, 49) _ 
        Order By rnd.Next() _ 
        Select n _ 
        Take 6 

'Do something with the numbers here 

Это простой способ сделать это. Если использование класса Random не является достаточно случайным, вам может потребоваться выбрать альтернативный метод.

0

Я думаю, что перетасовка является самой быстрой альтернативой. Но легче читать ваш подход в сочетании с коллекциями содержит функцию:

Dim numbers As New List(Of Int32) 
For i As Int32 = 1 To 6 
    Dim containsNextNumber As Boolean = False 
    While Not containsNextNumber 
     Dim rnd As New Random(Date.Now.Millisecond) 
     Dim nextNumber As Int32 = rnd.Next(1, 50) 
     If Not numbers.Contains(nextNumber) Then 
      numbers.Add(nextNumber) 
      containsNextNumber = True 
     End If 
    End While 
Next 
numbers.Sort() 'sort the numbers from low to high 
1

Вы должны изменить имя текстового поля, я использую, чтобы тот, который вы используете.

Dim rand As New Random 
    Dim winnum As New List(Of Integer) 
    Dim num, counter As Integer 
    Dim result As String = "" 

    Do 
     num = rand.Next(1, 49) 
     If winnum.Contains(num) Then 
      Do 
       num = rand.Next(1, 49) 
      Loop Until winnum.Contains(num) = False 
     End If 
     winnum.Add(num) 
     counter += 1 
    Loop Until counter = 6 

    'Extracting and displaying the numbers from the array 

    For n As Integer = 0 To 5 
     result = winnum(n) & " " & result 
    Next 

    'The textbox I'm using to display the result is result.text 

    result.Text = result 
1

Вы также можете использовать код в качестве другого человека, предложенного выше. В приведенном ниже коде числа генерируются случайным образом и удаляются из пула чисел до тех пор, пока не будет достигнуто требуемое количество. Затем отображаются цифры слева. Однако это не такой хороший способ для генерации чисел для лотереи, поскольку последовательность чисел как-то предсказуема, но они уникальны. Вот код:

Dim rand As New Random, winnum As New List(Of Integer) 
    Dim num As Integer, result As String = "" 

    For n As Integer = 1 To 49 
     winnum.Add(n) 
    Next 

    Do 
     num = rand.Next(1, 49) 

     If winnum.Contains(num) Then 
      winnum.Remove(num) 
     End If 

    Loop Until winnum.Count = 7 

    For n As Integer = 0 To 5 
     result = winnum(n) & " " & result 
    Next 

    a.Text = result