Bingo game: 2D Array and unique random numbers
Hi there,
For a school project I need to create a Bingo game based on a 2D Array.
Just like a real Bingo card the numbers need to be unique.
I managed to create a card with random numbers as shown in the code below, but I have no clue how to generate unique random numbers.
Any suggestions?
Code:
Public NotInheritable Class MainPage
Inherits Page
Dim BingoArray(7, 7) As Short
Dim generator As New Random
Dim size As Integer
Private Sub generateCardBtn_Click(sender As Object, e As RoutedEventArgs) Handles generateCardBtn.Click
Dim i As Integer 'amount rows (first dimension)
Dim j As Integer 'amount collumns (2nd dimension)
Dim k As Integer 'rows & collumns size
Dim minVal As Integer
Dim maxVal As Integer
Dim randNum As Integer
If twentyfiveRdBtn.IsChecked Then
size = 25
k = Math.Sqrt(size)
ReDim BingoArray(k, k) 'Redim card size
For i = 0 To BingoArray.GetUpperBound(0) - 1 'preserve one row in card / first dimension
For j = 0 To BingoArray.GetUpperBound(1) - 1 'preserve one row in card / second dimension
minVal = (i * 10) + 10
maxVal = (i * 10) + 20 - 1
randNum = generator.Next(minVal, maxVal)
BingoArray(i, j) = randNum
bingoCardTxtBox.Text += BingoArray(i, j) & " "
Next
bingoCardTxtBox.Text += vbNewLine
Next
End If
End Sub
End Class
Re: Bingo game: 2D Array and unique random numbers
The basic logic would be to keep a list of random numbers already chosen, and, after choosing a new random number, check to see if it is in the list of already chosen numbers. If it is, discard it and choose another. If it isn't, use it, and add it to the list of numbers already chosen.
Sorry, I won't provide code to do that. Good luck.
Re: Bingo game: 2D Array and unique random numbers
According to the rules, bingo numbers (American version) run from 1 - 75. "B" is 1 - 15, "I" is 16 - 30, "N" is 31 - 45, "G" is 46 - 60, and "O" is 61 - 75.
What you can do is generate the numbers in their own array using Enumerable.Range:
Code:
Dim b = Enumerable.Range(1, 15)
Dim i = Enumerable.Range(16, 30)
Dim n = Enumerable.Range(31, 45)
Dim g = Enumerable.Range(46, 50)
Dim o = Enumerable.Range(51, 75)
Now that the global numbers are declared, you can create a class to represent a user's "card". The properties names would be B, I, N, G, and O and each property would declared as an IEnumerable of integer. In the class' constructor you could even initialize the property value using the Random class:
Code:
Public Class BingoCard
Public Shared Function PossibleBValues() As IEnumerable(Of Integer)
Return Enumerable.Range(1, 15)
End Function
Public Shared Function PossibleIValues() As IEnumerable(Of Integer)
Return Enumerable.Range(16, 30)
End Function
Public Shared Function PossibleNValues() As IEnumerable(Of Integer)
Return Enumerable.Range(31, 45)
End Function
Public Shared Function PossibleGValues() As IEnumerable(Of Integer)
Return Enumerable.Range(46, 50)
End Function
Public Shared Function PossibleOValues() As IEnumerable(Of Integer)
Return Enumerable.Range(51, 75)
End Function
Public Property B As IEnumerable(Of Integer)
Public Property I As IEnumerable(Of Integer)
Public Property N As IEnumerable(Of Integer)
Public Property G As IEnumerable(Of Integer)
Public Property O As IEnumerable(Of Integer)
Private ReadOnly r As New Random()
Public Sub New()
B = Enumerable.Range(1, 5).Select(Function(value) r.Next(PossibleBValues().Min(), PossibleBValues().Max() + 1))
I = Enumerable.Range(1, 5).Select(Function(value) r.Next(PossibleIValues().Min(), PossibleIValues().Max() + 1))
N = Enumerable.Range(1, 5).Select(Function(value) r.Next(PossibleNValues().Min(), PossibleNValues().Max() + 1))
G = Enumerable.Range(1, 5).Select(Function(value) r.Next(PossibleGValues().Min(), PossibleGValues().Max() + 1))
O = Enumerable.Range(1, 5).Select(Function(value) r.Next(PossibleOValues().Min(), PossibleOValues().Max() + 1))
End Sub
End Class
Now whenever you create a new instance of a BingoCard, your properties will have random values within their expected range. With these values, you could loop over each property and do something with the values (like print them out on the screen).
Re: Bingo game: 2D Array and unique random numbers
Quote:
Originally Posted by
dday9
According to the rules, bingo numbers (American version) run from 1 - 75. "B" is 1 - 15, "I" is 16 - 30, "N" is 31 - 45, "G" is 46 - 60, and "O" is 61 - 75.
What you can do is generate the numbers in their own array using Enumerable.Range:
Code:
Dim b = Enumerable.Range(1, 15)
Dim i = Enumerable.Range(16, 30)
Dim n = Enumerable.Range(31, 45)
Dim g = Enumerable.Range(46, 50)
Dim o = Enumerable.Range(51, 75)
Now that the global numbers are declared, you can create a class to represent a user's "card". The properties names would be B, I, N, G, and O and each property would declared as an IEnumerable of integer. In the class' constructor you could even initialize the property value using the Random class:
Code:
Public Class BingoCard
Public Shared Function PossibleBValues() As IEnumerable(Of Integer)
Return Enumerable.Range(1, 15)
End Function
Public Shared Function PossibleIValues() As IEnumerable(Of Integer)
Return Enumerable.Range(16, 30)
End Function
Public Shared Function PossibleNValues() As IEnumerable(Of Integer)
Return Enumerable.Range(31, 45)
End Function
Public Shared Function PossibleGValues() As IEnumerable(Of Integer)
Return Enumerable.Range(46, 50)
End Function
Public Shared Function PossibleOValues() As IEnumerable(Of Integer)
Return Enumerable.Range(51, 75)
End Function
Public Property B As IEnumerable(Of Integer)
Public Property I As IEnumerable(Of Integer)
Public Property N As IEnumerable(Of Integer)
Public Property G As IEnumerable(Of Integer)
Public Property O As IEnumerable(Of Integer)
Private ReadOnly r As New Random()
Public Sub New()
B = Enumerable.Range(1, 5).Select(Function(value) r.Next(PossibleBValues().Min(), PossibleBValues().Max() + 1))
I = Enumerable.Range(1, 5).Select(Function(value) r.Next(PossibleIValues().Min(), PossibleIValues().Max() + 1))
N = Enumerable.Range(1, 5).Select(Function(value) r.Next(PossibleNValues().Min(), PossibleNValues().Max() + 1))
G = Enumerable.Range(1, 5).Select(Function(value) r.Next(PossibleGValues().Min(), PossibleGValues().Max() + 1))
O = Enumerable.Range(1, 5).Select(Function(value) r.Next(PossibleOValues().Min(), PossibleOValues().Max() + 1))
End Sub
End Class
Now whenever you create a new instance of a BingoCard, your properties will have random values within their expected range. With these values, you could loop over each property and do something with the values (like print them out on the screen).
Looks like that allows duplicates?
Re: Bingo game: 2D Array and unique random numbers
When the list is short, I think that the best option is to randomise the whole list and then just take items in order, e.g.
vb.net Code:
Private ReadOnly rng As New Random
Public ReadOnly Property B As ReadOnlyCollection(Of Integer)
Public ReadOnly Property I As ReadOnlyCollection(Of Integer)
Public ReadOnly Property N As ReadOnlyCollection(Of Integer)
Public ReadOnly Property G As ReadOnlyCollection(Of Integer)
Public ReadOnly Property O As ReadOnlyCollection(Of Integer)
Public Sub New()
B = GetNumbers(1, 15)
I = GetNumbers(16, 30)
N = GetNumbers(31, 45)
G = GetNumbers(46, 60)
O = GetNumbers(61, 75)
End Sub
Private Function GetNumbers(min As Integer, max As Integer) As ReadOnlyCollection(Of Integer)
Return New ReadOnlyCollection(Of Integer)(Enumerable.Range(min, max - min + 1).
OrderBy(Function(n) rng.NextDouble()).
Take(5).
ToArray())
End Function
Re: Bingo game: 2D Array and unique random numbers
This is my solution. I think this is the UK Version...
Code:
Public Class NumberUtilities
Public Shared Function baseNumbers() As Dictionary(Of Integer, List(Of Integer))
Dim numbers As New Dictionary(Of Integer, List(Of Integer))
Dim list1 As List(Of Integer) = Enumerable.Range(1, 10).ToList
numbers.Add(25, list1)
Dim list2 As List(Of Integer) = Enumerable.Range(11, 10).ToList
numbers.Add(75, list2)
Dim list3 As List(Of Integer) = Enumerable.Range(21, 10).ToList
numbers.Add(125, list3)
Dim list4 As List(Of Integer) = Enumerable.Range(31, 10).ToList
numbers.Add(175, list4)
Dim list5 As List(Of Integer) = Enumerable.Range(41, 10).ToList
numbers.Add(225, list5)
Dim list6 As List(Of Integer) = Enumerable.Range(51, 10).ToList
numbers.Add(275, list6)
Dim list7 As List(Of Integer) = Enumerable.Range(61, 10).ToList
numbers.Add(325, list7)
Dim list8 As List(Of Integer) = Enumerable.Range(71, 10).ToList
numbers.Add(375, list8)
Dim list9 As List(Of Integer) = Enumerable.Range(81, 11).ToList
numbers.Add(425, list9)
Return numbers
End Function
End Class
Code:
Public Class Form1
Dim r As New Random
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
DataGridView1.ColumnHeadersVisible = False
DataGridView1.RowHeadersVisible = False
DataGridView1.AllowUserToAddRows = False
DataGridView1.AllowUserToDeleteRows = False
DataGridView1.AllowUserToOrderColumns = False
DataGridView1.AllowUserToResizeColumns = False
DataGridView1.AllowUserToResizeRows = False
For x As Integer = 1 To 9
DataGridView1.Columns.Add(New DataGridViewTextBoxColumn)
DataGridView1.Columns(x - 1).Width = 30
Next
DataGridView1.Rows.Add(3)
Button1.PerformClick()
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim baseNumbers As Dictionary(Of Integer, List(Of Integer)) = NumberUtilities.baseNumbers
For y As Integer = 0 To 2
Dim c As Integer = 0
For x As Integer = 25 To 425 Step 50
Dim number As Integer = baseNumbers(x)(r.Next(0, baseNumbers(x).Count()))
baseNumbers(x).RemoveAt(baseNumbers(x).IndexOf(number))
DataGridView1.Rows(y).Cells(c).Value = number
c += 1
Next
Next
End Sub
End Class
I just converted that from my java version, but it's all there and working...
Re: Bingo game: 2D Array and unique random numbers
Just one remark about coding style:
Code:
Dim list1 As List(Of Integer) = Enumerable.Range(1, 10).ToList
This should work as well:
Code:
Dim list1 As New List(Of Integer)(Enumerable.Range(1, 10))