I was ready to do some more coding but I couldn’t think of a suitable project. Another game would have been ideal, to go alongside my other coding projects (cribbage, gin rummy, chess, backgammon, boxes).

I came up with the idea of coding the card game, sevens. It’s a simple game but I didn’t really think it would be much fun playing it against the computer. So I decided to code it as an exercise in testing various playing strategies rather than a game to be played. I was hoping to come up with four strategies for a four-player game and to see how they worked out with the computer playing all four hands. Unfortunately, the game is so simple I could only think of two strategies, a dumb one where the card choice is random, and an intelligent one. I could mix it up by getting the computer to play a mix of strategies, for example 1 dumb and 3 intelligent, or 2 dumb + 2 intelligent. So that’s what I did.

What did I discover?

Each trial was played over 100,000 games (taking 6 seconds on my laptop!)

  • If 4 dummies played against each other, the dummies each won 25% of games
  • If 4 smarties played against each other, the smarties each won 25% of games
  • If 1 dummy played against 3 smarties, the dummy won 13% of games, the smarties each won 29% of games
  • If 2 dummies played against 2 smarties, the dummies each won 13% of games, the smarties each won 37% of games
  • If 3 dummies played against 1 smarty, the dummies each won 17% of games, the smarty won 49% of games

Conclusion?

Although sevens is a simple card game and there’s the luck of the draw influencing who wins, it’s clear that one’s chances of winning can be significantly improved by playing the cards well. So it’s not entirely a game of chance!

The code

There aren’t that many lines of code but as usual I had issues with the logic and with finding bugs. An interesting bug that took me a long time to find, was as a result of me using the wrong format for a piece of code. See below.

I had written the following piece of code:

The wrong code

Select Case card
   Case 1 - 6
      direction = +1
   Case 7
      Return vbTrue
   Case Else
      direction = -1
End Select

The objective was to take different actions depending on whether the variable ‘card’ had a value between 1 and 6, or a value of 7, or any other value (actually between 8 and 13).

The bug was that ‘Case 1 – 6’ does not capture the range of values 1 to 6, but instead captures only the value -5 (ie 1-6). The result was that values between 1 and 6 were handled by the wrong piece of code, the Case Else code. This was a hard to spot bug! The correct code is on the right.

The correct code

Select Case card
   Case 1 TO 6
      direction = +1
   Case 7
      Return vbTrue
   Case Else
      direction = -1
End Select

The code for the two strategies

 Private Function PlayACard_strategy_1(player As Integer) As Boolean
     '
     ' Strategy-1: Choose a RANDOM playable card for the current player to play and play it.
     ' Return true if card played otherwise false if no card able to be played
     '
     Dim t As Integer

     nPlayableCards = 0
     Call GetPlayableCards(player)

     If Testing Then Call PrintCards(player)
     If Testing Then Call PrintPlayableCards()

     If nPlayableCards = 0 Then
         Return vbFalse
     End If

     t = Math.Min(CInt((nPlayableCards * Rnd()) + 1), nPlayableCards)
     PlayerCards(PlayableCardsCard(t), PlayableCardsSuit(t), player) = vbFalse ' Change status to card played
     If Testing Then Debug.Print("Player " & Str(player) & " randomly plays " & Str(PlayableCardsCard(t)))
     Return vbTrue

 End Function

 Private Function PlayACard_strategy_2(player As Integer) As Boolean
     '
     ' Strategy-2: Choose the BEST card for the current player to play and play it.
     ' Return true if card played otherwise false if no card able to be played
     '
     Dim i, card, suit As Integer

     nPlayableCards = 0
     Call GetPlayableCards(player)

     If Testing Then Call PrintCards(player)
     If Testing Then Call PrintPlayableCards()

     If nPlayableCards = 0 Then
         Return vbFalse
     End If

     For card = 1 To 7 ' Look for aces and kings, and if none then twos and queens, etc
         For suit = 1 To nSuits
             If PlayerCards(card, suit, player) Then ' If player has an ace (then up to 7) in this suit
                 For i = 1 To nPlayableCards
                     If PlayableCardsSuit(i) = suit And PlayableCardsCard(i) <= 7 Then ' if player has a playable card (7 or below)
                         PlayerCards(PlayableCardsCard(i), suit, player) = vbFalse ' Yes. Mark card as played
                         If Testing Then Debug.Print("Player " & Str(player) & " plays " & Str(PlayableCardsCard(i)))
                         Return vbTrue
                     End If
                 Next
             End If
             If PlayerCards(nCardsSuit + 1 - card, suit, player) Then ' If player has a king (then down to 7) in this suit
                 For i = 1 To nPlayableCards
                     If PlayableCardsSuit(i) = suit And PlayableCardsCard(i) >= 7 Then ' if player has a playable card (7 or above)
                         PlayerCards(PlayableCardsCard(i), suit, player) = vbFalse ' Yes. Mark card as played
                         If Testing Then Debug.Print("Player " & Str(player) & " plays " & Str(PlayableCardsCard(i)))
                         Return vbTrue
                     End If
                 Next
             End If
         Next
     Next

     MsgBox("We shouldn't ever get here!")

     Return vbTrue
 End Function

One response to “Sevens – another VBNET coding project”

  1. That’s not me. It’s an AI generated image of a bald, old guy!

Have your say! (No need for any ID!)