Public Class frmPoker
  Dim WithEvents cards As New DeckOfCards()

  Private Sub btnShuffle_Click(ByVal sender As System.Object,
                               ByVal e As System.EventArgs) Handles btnShuffle.Click
    cards.ShuffleDeck()
  End Sub

  Private Sub btnDeal_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDeal.Click
    Dim str As String
    lstHand.Items.Clear()
    For i As Integer = 0 To 4
      str = cards.ReadCard(i)
      lstHand.Items.Add(str)
    Next
  End Sub

  Private Sub btnQuit_Click(ByVal sender As System.Object,
                            ByVal e As System.EventArgs) Handles btnQuit.Click
    Me.Close()
  End Sub

  Private Sub cards_Shuffling(ByVal n As Integer,
                              ByVal nMax As Integer) Handles cards.Shuffling
    'n is the number of the specific pass through the deck (1, 2, 3...)
    'nMax is the total number of passes when the deck is shuffled.
    lstHand.Items.Clear()
    lstHand.Items.Add("Shuffling Pass: " & n & " out of " & nMax)
    For i As Integer = 1 To 1000000     'Slow down the shuffle.
    Next
    lstHand.Update()         'Refresh contents of list box
  End Sub
End Class     'frmPoker

Class Card
  Private m_denomination As Integer  'A number from 0 through 12
  Private m_suit As String           'Hearts, Clubs, Diamonds, Spades

  Public Property Denomination() As Integer
    Get
      Return m_denomination
    End Get
    Set(ByVal value As Integer)
      'Only store valid values.
      If (value >= 0) And (value <= 12) Then
        m_denomination = value
      End If
    End Set
  End Property

  Public Property Suit() As String
    Get
      Return m_suit
    End Get
    Set(ByVal value As String)
      'Only store valid values.
      If (value = "Hearts") Or (value = "Clubs") Or (value = "Diamonds") Or
                               (value = "Spades") Then
        m_suit = value
      End If
    End Set
  End Property

  Function IdentifyCard() As String
    Dim denom As String = ""
    Select Case Denomination + 1
      Case 1
        denom = "Ace"
      Case Is <= 10
        denom = CStr(Denomination + 1)
      Case 11
        denom = "Jack"
      Case 12
        denom = "Queen"
      Case 13
        denom = "King"
    End Select
    Return denom & " of " & Suit
  End Function
End Class     'Card

Class DeckOfCards
  Private m_deck(51) As Card    'Class DeckOfCards contains class Card
  Public Event Shuffling(ByVal n As Integer, ByVal nMax As Integer)

  Public Sub New()
    'Make the first thirteen cards hearts, the
    'next thirteen cards diamonds, and so on.
    Dim suits() As String = {"Hearts", "Clubs", "Diamonds", "Spades"}
    For i As Integer = 0 To 3
      'Each pass corresponds to one of the four suits.
      For j As Integer = 0 To 12
        'Assign numbers from 1 through 13 to the 
        'cards of each suit.
        m_deck(i * 13 + j) = New Card()
        m_deck(i * 13 + j).Suit = suits(i)
        m_deck(i * 13 + j).Denomination = j
      Next
    Next
  End Sub

  Function ReadCard(ByVal cardNum As Integer) As String
    Return m_deck(cardNum).IdentifyCard()
  End Function

  Sub Swap(ByVal i As Integer, ByVal j As Integer)
    'Swap the ith and jth cards in the deck.
    Dim tempCard As Card
    tempCard = m_deck(i)
    m_deck(i) = m_deck(j)
    m_deck(j) = tempCard
  End Sub

  Sub ShuffleDeck()
    'Do 2000 passes through the deck.  On each pass
    'swap each card with a randomly selected card.
    Dim index As Integer
    Dim randomNum As New Random()
    For i As Integer = 1 To 2000
      For k As Integer = 0 To 51
        index = randomNum.Next(0, 52)  'Randomly select a number
        '                               from 0 through 51 inclusive.
        Swap(k, index)
      Next
      RaiseEvent Shuffling(i, 2000)
    Next
  End Sub
End Class     'DeckOfCards
