VB 2010 - minimal comments so that students will have to figure it out
Code:
Public Class Form1
'Bingo Master - used by the person calling the Letter / Number combination's.
'Create a new form (500w x 600h) and add a TableLayoutPanel, 2 Buttons and 2 Labels.
'TableLayoutPanel1
'Button1
'Button2
'Label1
'Label2
'The TableLayoutPanel should be in the upper left corner of the form.
'Label1 in the lower right corner, with Button1 and Button2 above the label
'Label2 in the lower left corner
'numsPerCol = the number of numbers per column:
'American bingo = 15
'other countries = 18
Const numsPerCol As Integer = 15
Dim colHeaders() As Char = New Char() {"B"c, "I"c, "N"c, "G"c, "O"c} 'the column headers ' Normally BINGO
Const hMinSiz As Integer = 470
Const wMinSiz As Integer = 450
Dim totNums As Integer = numsPerCol * colHeaders.Length
Dim numsCalled As Integer
Dim card As New Dictionary(Of String, Label)
Enum calledState
called = -6751336 'Color.PaleGreen.ToArgb
notcalled = -7876870 'Color.LightSkyBlue.ToArgb
End Enum
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
'new game
For Each kvp As KeyValuePair(Of String, Label) In card
kvp.Value.BackColor = Color.FromArgb(calledState.notcalled) ' notCalledColor
kvp.Value.Tag = calledState.notcalled '"nc"
Next
numsCalled = 0
Label1.Text = "New Game"
Label2.Text = ""
Button2.Select()
End Sub
Dim PRNG As New Random
Private Sub Button2_Click(sender As System.Object, _
e As System.EventArgs) Handles Button2.Click
'call a number at random
If numsCalled >= totNums Then
Label1.Text = "Game over"
Exit Sub
End If
Dim bar As List(Of KeyValuePair(Of String, Label)) 'results
'get the not called numbers
bar = (From kvp In card Where DirectCast(kvp.Value.Tag, calledState) = calledState.notcalled Select kvp).ToList
If bar.Count > 0 Then
Dim idx As Integer = PRNG.Next(bar.Count)
Dim foo As KeyValuePair(Of String, Label) = bar(idx)
SelectSQ(foo.Value)
End If
End Sub
Public Function crLabel() As Label
Static lblW As Integer = (TableLayoutPanel1.Width \ colHeaders.Length) - 2
Static lblH As Integer = (TableLayoutPanel1.Height \ (numsPerCol + 1)) - 2
'create a label that will fit in a tlp cell
Dim foo As New Label
foo.AutoSize = False
foo.Width = lblW
foo.Height = lblH
foo.TextAlign = ContentAlignment.MiddleCenter
foo.BorderStyle = BorderStyle.FixedSingle
foo.Tag = calledState.notcalled
Return foo
End Function
Private Sub GenericClick(ByVal sender As System.Object, _
ByVal e As System.EventArgs)
SelectSQ(sender)
End Sub
Private Sub SelectSQ(sender As System.Object)
Dim lbl As Label = CType(sender, Label)
If DirectCast(lbl.Tag, calledState) = calledState.notcalled Then
numsCalled += 1
lbl.Tag = calledState.called
lbl.BackColor = Color.FromArgb(calledState.called)
Label1.Text = lbl.Text
Label2.Text = Label2.Text.Insert(0, " . " & lbl.Text)
If Label2.Text.Length > 60 Then
Dim foo As Integer = Label2.Text.LastIndexOf(".")
Label2.Text = Label2.Text.Substring(0, foo)
End If
Dim dp As Drawing.Point = lbl.Location
dp.X += TableLayoutPanel1.Location.X + 4
dp.Y += TableLayoutPanel1.Location.Y + 4
Cursor.Position = PointToScreen(dp)
End If
End Sub
Private Sub Form1_Shown(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles Me.Shown
Label1.TextAlign = ContentAlignment.MiddleRight
TableLayoutPanel1.Controls.Clear() 'clear the tlp
TableLayoutPanel1.ColumnStyles.Clear()
TableLayoutPanel1.RowStyles.Clear()
If TableLayoutPanel1.Width < wMinSiz Then TableLayoutPanel1.Width = wMinSiz 'set minimum size
If TableLayoutPanel1.Height < hMinSiz Then TableLayoutPanel1.Height = hMinSiz
Dim colPercent As Single = CSng(100 / colHeaders.Length) 'calculate the size of the columns
Dim rowPercent As Single = CSng(100 / (numsPerCol + 1)) ' and rows
TableLayoutPanel1.ColumnCount = colHeaders.Length 'set the number of columns
TableLayoutPanel1.RowCount = numsPerCol + 1 'and rows
'set the size of the columns
For idx As Integer = 0 To colHeaders.Length - 1
TableLayoutPanel1.ColumnStyles.Add(New ColumnStyle(SizeType.Percent, colPercent))
Next
'set the size of the rows
For idx As Integer = 0 To numsPerCol
TableLayoutPanel1.RowStyles.Add(New RowStyle(SizeType.Percent, rowPercent))
Next
'set the value of each cell
For col As Integer = 0 To colHeaders.Length - 1
Dim foo As Label = crLabel()
foo.Text = colHeaders(col)
TableLayoutPanel1.Controls.Add(foo, col, 0) 'set the header
For row As Integer = 1 To numsPerCol
foo = crLabel()
AddHandler foo.Click, AddressOf GenericClick
foo.Text = colHeaders(col) & " " & (col * numsPerCol + row).ToString
TableLayoutPanel1.Controls.Add(foo, col, row)
card.Add(foo.Text, foo)
Next
Next
Button1.PerformClick()
End Sub
End Class