Overview

[Quote wiki: https://en.wikipedia.org/wiki/Three-card_Monte]

"Three-card Monte - also known as find the lady and three-card trick - is a confidence game in which the victim, or "mark", is tricked into betting a sum of money, on the assumption that they can find the "money card" among three face-down playing cards. It is the same as the shell game except that cards are used instead of shells.

In its full form, three-card Monte is an example of a classic "short con" in which a shill pretends to conspire with the mark to cheat the dealer, while in fact conspiring with the dealer to cheat the mark. The mark has no chance whatsoever of winning, at any point in the game. In fact, anyone who is observed winning anything in the game can be presumed to be a shill.

This confidence trick was already in use by the turn of the 15th century."

This is a card game based on Three-card Monte, with the exception being, this is the honest version.


The levelControl

This control is hosted in a menuitem and used for setting the speed of card shuffling.

Public Class levelControl
 
 Public Event ValueChanged(sender As Object, e As EventArgs)
 
 Public Property Value() As Integer
 Get
 Return HScrollBar1.Value
 End Get
 Set(ByVal value As Integer)
 HScrollBar1.Value = value
 End Set
 End Property
 
 Public Property Minimum() As Integer
 Get
 Return HScrollBar1.Minimum
 End Get
 Set(ByVal value As Integer)
 HScrollBar1.Minimum = value
 End Set
 End Property
 Public Property Maximum() As Integer
 Get
 Return HScrollBar1.Maximum
 End Get
 Set(ByVal value As Integer)
 HScrollBar1.Maximum = value
 End Set
 End Property
 
 Private Sub HScrollBar1_ValueChanged(sender As Object, e As EventArgs) Handles HScrollBar1.ValueChanged
 RaiseEvent ValueChanged(Me, New EventArgs)
 End Sub
 
End Class

The Form code

Most of the code is encapsulated in Form1. This is because, as a highly graphical game, it wouldn't be appropriate to move the code to Classes. The cost would outweigh the benefits in terms of code concision...
Public Class Form1
 
 Dim images As New Dictionary(Of Object, Bitmap)
 
 'these 6 arrays are used in the animation effects
 Dim Points1() As Point = New Point() {
 New Point(388, 186),
 New Point(388, 161),
 New Point(368, 136),
 New Point(338, 116),
 New Point(298, 116),
 New Point(268, 136),
 New Point(248, 161),
 New Point(248, 186)}
 
 Dim Points2() As Point = New Point() {
 New Point(248, 186),
 New Point(248, 211),
 New Point(268, 236),
 New Point(298, 256),
 New Point(338, 256),
 New Point(368, 236),
 New Point(388, 211),
 New Point(388, 186)}
 
 Dim Points3() As Point = New Point() {
 New Point(248, 186),
 New Point(248, 161),
 New Point(228, 136),
 New Point(198, 116),
 New Point(158, 116),
 New Point(128, 136),
 New Point(108, 161),
 New Point(108, 186)}
 
 
 Dim Points4() As Point = New Point() {
 New Point(108, 186),
 New Point(108, 211),
 New Point(128, 236),
 New Point(158, 256),
 New Point(198, 256),
 New Point(228, 236),
 New Point(248, 211),
 New Point(248, 186)}
 
 
 Dim Points5() As Point = New Point() {
 New Point(388, 186),
 New Point(388, 161),
 New Point(368, 136),
 New Point(338, 116),
 New Point(298, 96),
 New Point(248, 96),
 New Point(198, 96),
 New Point(158, 116),
 New Point(128, 136),
 New Point(108, 161),
 New Point(108, 186)}
 
 
 Dim Points6() As Point = New Point() {
 New Point(108, 186),
 New Point(108, 211),
 New Point(128, 236),
 New Point(158, 256),
 New Point(198, 276),
 New Point(248, 276),
 New Point(298, 276),
 New Point(338, 256),
 New Point(368, 236),
 New Point(388, 211),
 New Point(388, 186)}
 
 Dim upper() As Point = Nothing
 Dim lower() As Point = Nothing
 Dim loopIndex As Integer
 Dim increment As Integer
 Dim fixed As Integer
 Dim showCards As Boolean = False
 Dim r As New Random
 Dim sw As New Stopwatch
 Dim after() As String
 Dim rgns(2) As Region
 Dim showFace() As Boolean
 Dim canChoose As Boolean = False
 
 Private WithEvents tmr As New Timer With {.Interval = 40}
 Private WithEvents hsb As New levelControl With {.Minimum = 25, .Maximum = 100, .Value = 40}
 
 'clickable regions are used in allowing the card images to respond to clicking
 Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
 images.Add("Queen", My.Resources.queen)
 images.Add("King", My.Resources.king)
 images.Add("Ace", My.Resources.ace)
 images.Add("Back", My.Resources.back)
 
 Dim r As New Rectangle(New Point(Points4(0).X - 36, Points4(0).Y - 48), New Size(72, 96))
 rgns(0) = New Region(r)
 r = New Rectangle(New Point(Points2(0).X - 36, Points2(0).Y - 48), New Size(72, 96))
 rgns(1) = New Region(r)
 r = New Rectangle(New Point(Points1(0).X - 36, Points1(0).Y - 48), New Size(72, 96))
 rgns(2) = New Region(r)
 
 DifficultyToolStripMenuItem.DropDownItems.Add(New ToolStripControlHost(hsb))
 
 Me.DoubleBuffered = True
 Me.SetClientSizeCore(504, 396)
 End Sub
 
 'captures card clicking
 Private Sub Form1_MouseDown(sender As Object, e As MouseEventArgs) Handles Me.MouseDown
 If e.Button = MouseButtons.Left Then
 If canChoose Then
 Dim x As Integer = Array.FindIndex(rgns, Function(rgn) rgn.IsVisible(e.Location))
 If x > -1 Then
 showFace(x) = True
 canChoose = False
 Button1.Enabled = True
 Me.Refresh()
 End If
 End If
 End If
 End Sub
 
 'the animations are purely GDI+
 Private Sub Form1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
 If showcards Then
 e.Graphics.DrawImage(If(showFace(0), images(after(0)), images("Back")), New Point(Points4(0).X - 36, Points4(0).Y - 48))
 e.Graphics.DrawImage(If(showFace(1), images(after(1)), images("Back")), New Point(Points2(0).X - 36, Points2(0).Y - 48))
 e.Graphics.DrawImage(If(showFace(2), images(after(2)), images("Back")), New Point(Points1(0).X - 36, Points1(0).Y - 48))
 Return
 End If
 If upper Is Nothing Then Return
 Select Case fixed
 Case 0
 e.Graphics.DrawImage(images("Back"), New Point(Points4(0).X - 36, Points4(0).Y - 48))
 Case 1
 e.Graphics.DrawImage(images("Back"), New Point(Points2(0).X - 36, Points2(0).Y - 48))
 Case 2
 e.Graphics.DrawImage(images("Back"), New Point(Points1(0).X - 36, Points1(0).Y - 48))
 End Select
 e.Graphics.DrawImage(images("Back"), New Point(upper(loopIndex).X - 36, upper(loopIndex).Y - 48))
 e.Graphics.DrawImage(images("Back"), New Point(lower(loopIndex).X - 36, lower(loopIndex).Y - 48))
 End Sub
 
 Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
 Button1.Enabled = False
 after = New String() {"Queen", "King", "Ace"}.OrderBy(Function(s) r.NextDouble).ToArray
 showFace = New Boolean() {True, True, True}
 showcards = True
 Me.Refresh()
 Threading.Thread.Sleep(1250)
 showFace = New Boolean() {False, True, True}
 Me.Refresh()
 Threading.Thread.Sleep(250)
 showFace = New Boolean() {False, False, True}
 Me.Refresh()
 Threading.Thread.Sleep(250)
 showFace = New Boolean() {False, False, False}
 Me.Refresh()
 Threading.Thread.Sleep(250)
 nextMove()
 sw = Stopwatch.StartNew()
 tmr.Enabled = True
 End Sub
 
 Private Sub tmr_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles tmr.Tick
 showcards = False
 If increment = -1 Then
 If loopIndex + increment < 0 Then
 If sw.Elapsed < New TimeSpan(0, 0, 10) Then
 nextMove()
 Else
 tmr.Stop()
 showcards = True
 canChoose = True
 End If
 Else
 loopIndex += increment
 End If
 Else
 If loopIndex + increment > upper.GetUpperBound(0) Then
 If sw.Elapsed < New TimeSpan(0, 0, 10) Then
 nextMove()
 Else
 tmr.Stop()
 showcards = True
 canChoose = True
 End If
 Else
 loopIndex += increment
 End If
 End If
 Me.Refresh()
 End Sub
 
 'this method changes the variables used in the animation, allowing different moves
 Private Sub nextMove()
 Dim move As Integer = r.Next(0, 6)
 
 Select Case move
 Case 0
 upper = Points1
 lower = Points2
 increment = 1
 fixed = 0
 loopIndex = 0
 Dim temp As String = after(1)
 after(1) = after(2)
 after(2) = temp
 Case 1
 upper = Points3
 lower = Points4
 increment = 1
 fixed = 2
 loopIndex = 0
 Dim temp As String = after(0)
 after(0) = after(1)
 after(1) = temp
 Case 2
 upper = Points5
 lower = Points6
 increment = 1
 fixed = 1
 loopIndex = 0
 Dim temp As String = after(0)
 after(0) = after(2)
 after(2) = temp
 Case 3
 upper = Points1
 lower = Points2
 increment = -1
 fixed = 0
 loopIndex = upper.GetUpperBound(0)
 Dim temp As String = after(2)
 after(2) = after(1)
 after(1) = temp
 Case 4
 upper = Points3
 lower = Points4
 increment = -1
 fixed = 2
 loopIndex = upper.GetUpperBound(0)
 Dim temp As String = after(0)
 after(0) = after(1)
 after(1) = temp
 Case 5
 upper = Points5
 lower = Points6
 increment = -1
 fixed = 1
 loopIndex = upper.GetUpperBound(0)
 Dim temp As String = after(0)
 after(0) = after(2)
 after(2) = temp
 End Select
 
 End Sub
 Private Sub hsb_ValueChanged(sender As Object, e As EventArgs) Handles hsb.ValueChanged
 tmr.Interval = hsb.Value
 End Sub
 
End Class

Conclusion

This example shows how to create a lightweight GDI+ card game, with simple animations.


Articles related to game programming

 


Download

Download here