Full disclosure: This is my last stop. I have already done a fair amount of research on this issue. While I've come across lots of implementations of this project, I've not seen this weird behavior anywhere else.

The project: As one of the projects for my Advanced Visual Basic course, I'm implementing a Concentration game very much like this project: http://www.vb6.us/source-code/full-vb6-game-concentration

The issue: I've got most of the logic working but I'm getting really weird behavior when I flip the cards. The first one flips fine. The second one is *supposed* to flip and hold for a second (I use a Thread.Threading.sleep(1000)) then flip back to covered if they're not a match.

If they match it works as intended.

For some reason, if they don't match it never flips the second card over so that you can see the picture underneath. It evaluates correctly but if the pics don't match, you never get to see the 2nd card.

Secondary issue (not as critical): At lines 67-79 there are some bits of code that are commented out. I'm trying to use a For Each loop to go through all my picture box controls and assign them to the array of structures and then assign the cover image without having to do it one at a time. It would save me about 250 lines of code and help me to still respect myself in the morning. Advice here is welcome as well.

In addition to including my code, I will upload a copy of the entire project folder in case anyone wants to compile it and see the behavior for themselves. Any help is much appreciated!

I tried to comment the bejesus out of my code:

Public Class hard


    'declare arrays
    Friend pic(19) As pics
    Dim picBoxes(35) As picBox

    'Declare structures
    Friend Structure pics
        Dim pictures As Image
        Dim used As Integer
        Dim pos As Integer
    End Structure

    Friend Structure picBox
        Dim photo As Image
        Dim cover As Image
        Dim pictureBox As PictureBox
        Dim pos As Integer
    End Structure

    'Declare global variables
    Dim clicked As Integer = 0
    Dim pb1 As picBox
    Dim pb2 As picBox
    Dim matches As Integer = 0
    Dim attempts As Integer = 0



    'Set up Game board
    Private Sub hard_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        'generate new random seed
        Randomize()

        'Populate pictures array
        pic(0).pictures = My.Resources.ImperialLogo
        pic(1).pictures = My.Resources.picard
        pic(2).pictures = My.Resources.arwen
        pic(3).pictures = My.Resources.chewie
        pic(4).pictures = My.Resources.deathStar
        pic(5).pictures = My.Resources.enterprise
        pic(6).pictures = My.Resources.fett
        pic(7).pictures = My.Resources.freeman
        pic(8).pictures = My.Resources.gandalf
        pic(9).pictures = My.Resources.han
        pic(10).pictures = My.Resources.interceptor
        pic(11).pictures = My.Resources.kirk
        pic(12).pictures = My.Resources.sam
        pic(13).pictures = My.Resources.saruman
        pic(14).pictures = My.Resources.scotty
        pic(15).pictures = My.Resources.starTrek
        pic(16).pictures = My.Resources.trooper
        pic(17).pictures = My.Resources.wheaton
        pic(18).pictures = My.Resources.yoda




        '
        'BEGIN BOARD INIT
        '

        'assign PictureBoxes to all 36 elements of the picBoxes array of Structures
        'assign ImperialLogo to the cover member of picBoxes array of structures
        'Cover member (ImperialLogo) is visible by default
        'For Each pictureBox As PictureBox In Me.Controls
        '    Dim x As Integer = 1
        '    Dim pbName As String = "PictureBox" + x.ToString

        '    If TypeOf pictureBox Is PictureBox Then
        '        With picBoxes(x)
        '            .pictureBox = pictureBox.Name
        '            .cover = My.Resources.ImperialLogo
        '            .pictureBox.Image = .cover
        '        End With
        '    End If
        '    x += 1
        'Next

        With picBoxes(0)
            .pictureBox = PictureBox1
            .cover = My.Resources.ImperialLogo
            .pictureBox.Image = .cover
        End With

        With picBoxes(1)
            .pictureBox = PictureBox2
            .cover = My.Resources.ImperialLogo
            .pictureBox.Image = .cover
        End With

        With picBoxes(2)
            .pictureBox = PictureBox3
            .cover = My.Resources.ImperialLogo
            .pictureBox.Image = .cover
        End With

        With picBoxes(3)
            .pictureBox = PictureBox4
            .cover = My.Resources.ImperialLogo
            .pictureBox.Image = .cover
        End With

        With picBoxes(4)
            .pictureBox = PictureBox5
            .cover = My.Resources.ImperialLogo
            .pictureBox.Image = .cover
        End With

        With picBoxes(5)
            .pictureBox = PictureBox6
            .cover = My.Resources.ImperialLogo
            .pictureBox.Image = .cover
        End With

        With picBoxes(6)
            .pictureBox = PictureBox7
            .cover = My.Resources.ImperialLogo
            .pictureBox.Image = .cover
        End With

        With picBoxes(7)
            .pictureBox = PictureBox8
            .cover = My.Resources.ImperialLogo
            .pictureBox.Image = .cover
        End With

        With picBoxes(8)
            .pictureBox = PictureBox9
            .cover = My.Resources.ImperialLogo
            .pictureBox.Image = .cover
        End With

        With picBoxes(9)
            .pictureBox = PictureBox10
            .cover = My.Resources.ImperialLogo
            .pictureBox.Image = .cover
        End With

        With picBoxes(10)
            .pictureBox = PictureBox11
            .cover = My.Resources.ImperialLogo
            .pictureBox.Image = .cover
        End With


        With picBoxes(11)
            .pictureBox = PictureBox12
            .cover = My.Resources.ImperialLogo
            .pictureBox.Image = .cover
        End With

        With picBoxes(12)
            .pictureBox = PictureBox13
            .cover = My.Resources.ImperialLogo
            .pictureBox.Image = .cover
        End With

        With picBoxes(13)
            .pictureBox = PictureBox14
            .cover = My.Resources.ImperialLogo
            .pictureBox.Image = .cover
        End With

        With picBoxes(14)
            .pictureBox = PictureBox15
            .cover = My.Resources.ImperialLogo
            .pictureBox.Image = .cover
        End With

        With picBoxes(15)
            .pictureBox = PictureBox16
            .cover = My.Resources.ImperialLogo
            .pictureBox.Image = .cover
        End With

        With picBoxes(16)
            .pictureBox = PictureBox17
            .cover = My.Resources.ImperialLogo
            .pictureBox.Image = .cover
        End With

        With picBoxes(17)
            .pictureBox = PictureBox18
            .cover = My.Resources.ImperialLogo
            .pictureBox.Image = .cover
        End With

        With picBoxes(18)
            .pictureBox = PictureBox19
            .cover = My.Resources.ImperialLogo
            .pictureBox.Image = .cover
        End With

        With picBoxes(19)
            .pictureBox = PictureBox20
            .cover = My.Resources.ImperialLogo
            .pictureBox.Image = .cover
        End With

        With picBoxes(20)
            .pictureBox = PictureBox21
            .cover = My.Resources.ImperialLogo
            .pictureBox.Image = .cover
        End With

        With picBoxes(21)
            .pictureBox = PictureBox22
            .cover = My.Resources.ImperialLogo
            .pictureBox.Image = .cover
        End With

        With picBoxes(22)
            .pictureBox = PictureBox23
            .cover = My.Resources.ImperialLogo
            .pictureBox.Image = .cover
        End With

        With picBoxes(23)
            .pictureBox = PictureBox24
            .cover = My.Resources.ImperialLogo
            .pictureBox.Image = .cover
        End With

        With picBoxes(24)
            .pictureBox = PictureBox25
            .cover = My.Resources.ImperialLogo
            .pictureBox.Image = .cover
        End With

        With picBoxes(25)
            .pictureBox = PictureBox26
            .cover = My.Resources.ImperialLogo
            .pictureBox.Image = .cover
        End With

        With picBoxes(26)
            .pictureBox = PictureBox27
            .cover = My.Resources.ImperialLogo
            .pictureBox.Image = .cover
        End With

        With picBoxes(27)
            .pictureBox = PictureBox28
            .cover = My.Resources.ImperialLogo
            .pictureBox.Image = .cover
        End With

        With picBoxes(28)
            .pictureBox = PictureBox29
            .cover = My.Resources.ImperialLogo
            .pictureBox.Image = .cover
        End With

        With picBoxes(29)
            .pictureBox = PictureBox30
            .cover = My.Resources.ImperialLogo
            .pictureBox.Image = .cover
        End With

        With picBoxes(30)
            .pictureBox = PictureBox31
            .cover = My.Resources.ImperialLogo
            .pictureBox.Image = .cover
        End With

        With picBoxes(31)
            .pictureBox = PictureBox32
            .cover = My.Resources.ImperialLogo
            .pictureBox.Image = .cover
        End With

        With picBoxes(32)
            .pictureBox = PictureBox33
            .cover = My.Resources.ImperialLogo
            .pictureBox.Image = .cover
        End With

        With picBoxes(33)
            .pictureBox = PictureBox34
            .cover = My.Resources.ImperialLogo
            .pictureBox.Image = .cover
        End With

        With picBoxes(34)
            .pictureBox = PictureBox35
            .cover = My.Resources.ImperialLogo
            .pictureBox.Image = .cover
        End With

        With picBoxes(35)
            .pictureBox = PictureBox36
            .cover = My.Resources.ImperialLogo
            .pictureBox.Image = .cover
        End With

        '
        'END BOARD INIT
        '




        'intialize counters
        Dim i As Integer = 0
        Dim j As Integer = 1

        'load board with random pics
        For i = 0 To 36
            Dim rand As Integer
            'create randome integer to assign
            rand = (Rnd() * 17) + 1
            'if pic has already been used twice, systematically check 
            'each picture's used member in pics
            While pic(rand).used >= 2
                If pic(j).used >= 2 Then
                    j = j + 1
                Else
                    rand = j
                    Exit While
                End If
            End While

            'if the picture has been used fewer than two times, 
            'then assign it to a random picturebox
            'Assign the matching index of the picture from the pics Array to .pos 
            If pic(rand).used < 2 Then
                picBoxes(i).photo = pic(rand).pictures
                picBoxes(i).pos = rand
                pic(rand).used = pic(rand).used + 1
            End If
        Next
    End Sub


    'method to test whether a match has been made
    Private Sub testForMatch(ByVal incPb As picBox)

        Dim thisPB As picBox
        thisPB = incPb

        'A turn (or attempt) is two clicks
        'On the first click, only increment the clicked field
        If clicked < 1 Then
            'set incoming PictureBox to temporary object
            pb1 = thisPB
            pb1.pictureBox.Image = pb1.photo
            clicked = clicked + 1

            'On the second click, increment clicked again
        ElseIf clicked < 2 Then
            'set incoming PictureBox to temporary object
            pb2 = thisPB
            pb2.pictureBox.Image = pb2.photo
            clicked = clicked + 1
            'log the attempt whether successful or not, display it in the attemptsL.text
            attempts = attempts + 1
            attemptsL.Text = attempts
            'On the second click, compare the integers associated with each photo
            If pb1.pos = pb2.pos Then  'If they match...
                'Log the match and display it in the matchesL.text
                matches = matches + 1
                MatchesL.Text = matches
                'reset clicked for the next attempt
                clicked = 0
                'disable the PictureBoxes
                pb1.pictureBox.Enabled = False
                pb2.pictureBox.Enabled = False
            Else 'if they are not a match
                'hold for 1 second before switching back
                Threading.Thread.Sleep(1000)
                'reset clicked
                clicked = 0
                'reset the cards back to .cover
                pb1.pictureBox.Image = pb1.cover
                pb2.pictureBox.Image = pb2.cover
            End If

        End If


    End Sub

    'Any time the mouse hovers, perform a check to see if the player has won.
    Private Sub hard_MouseHover(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.MouseHover
        If matches >= 18 Then
            MsgBox("YOU WIN!!")
            Me.Close()
        End If
    End Sub

    'method to handle click events for the picture boxes
    Private Sub PictureBox1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles PictureBox1.Click, PictureBox2.Click, PictureBox3.Click, PictureBox4.Click, _
        PictureBox5.Click, PictureBox6.Click, PictureBox7.Click, PictureBox8.Click, PictureBox9.Click, PictureBox10.Click, PictureBox11.Click, PictureBox12.Click, _
        PictureBox13.Click, PictureBox14.Click, PictureBox15.Click, PictureBox16.Click, PictureBox17.Click, PictureBox18.Click, PictureBox19.Click, PictureBox20.Click, _
        PictureBox21.Click, PictureBox22.Click, PictureBox23.Click, PictureBox24.Click, PictureBox25.Click, PictureBox26.Click, PictureBox27.Click, PictureBox28.Click, _
        PictureBox29.Click, PictureBox30.Click, PictureBox31.Click, PictureBox32.Click, PictureBox33.Click, PictureBox34.Click, PictureBox35.Click, PictureBox36.Click


        'When a pictureBox is clicked...
        'create a local object to be sent to oneTurn()
        Dim thisPicBox As picBox
        Dim pbNum As Integer
        Dim pbNumString As String
        'get the index of the pictureBox clicked
        thisPicBox.pictureBox = TryCast(sender, PictureBox)
        pbNumString = thisPicBox.pictureBox.Name.Substring(10)
        pbNum = Convert.ToInt32(pbNumString) - 1
        'set thisPicBox to the picbox clicked
        thisPicBox = picBoxes(pbNum)
        ' 'flip' the card
        thisPicBox.pictureBox.Image = thisPicBox.photo
        'call oneTurn() to evaluate whether a match has been made
        testForMatch(thisPicBox)
    End Sub


End Class

Secondary issue, see if this helps.

For i As Integer = 0 To picBoxes.Length - 1
            With picBoxes(i)
                .pictureBox = CType(Me.Controls("PictureBox" & i + 1), PictureBox)
                .cover = My.Resources.ImperialLogo
                .pictureBox.Image = .cover
            End With
        Next

edit::
To make it easier on you the next time you need to add more than one control to an event, use something as this in Form_Load, instead of adding "pic1.click, pic2.click, picEtc.click".

For i As Integer = 1 To 36
            With CType(Me.Controls("PictureBox" & i), PictureBox)
                AddHandler .Click, AddressOf PictureBox1_Click
            End With
        Next

Hope this helps.:)

Edited 4 Years Ago by codeorder: n/a

Please Download the attachments....

And see the code..

step by step..

1. A Pic Class is there for custome picture control
2. In the main form create pic object as many you want... Each pic card will animate..
3. Now see the whole coding of form1 where the main things done...

http://www.mediafire.com/?ll3zbtatafdbuok


The Pic Class
________________________________________

Public Class pic
    Dim t As New Timer
    Dim p As New Panel
    Dim actualpic As Image
    Dim i As Boolean = True
    Public Shared cnt As Integer
    Public fac As Boolean = False
    Dim stat As Boolean = False
    Dim imid As Integer
    Public Sub setStat()
        stat = True
    End Sub
    Public Sub New(ByVal imgid As Integer, ByVal Pwidth As Integer, ByVal Pheight As Integer)
        p.Height = Pheight
        p.Width = Pwidth
        p.BackColor = Color.Black
        imid = imgid
        actualpic = Form1.il.Images.Item(imgid)
        AddHandler p.Click, AddressOf Panel1_Click
        AddHandler t.Tick, AddressOf Timer1_Tick
    End Sub

    Private Sub Panel1_Click(ByVal sender As Object, ByVal e As System.EventArgs)
        If cnt > 1 Or stat Then
            Exit Sub
        End If
        t.Interval = 1
        t.Start()

        'MsgBox(cnt.ToString)
    End Sub
    Public Sub faceoff()
        fac = True
        t.Interval = 1
        t.Start()
    End Sub

    Public Sub setpos(ByVal lft As Integer, ByVal tp As Integer)
        p.Left = lft
        p.Top = tp
    End Sub
    Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs)
        If fac = False Then
            If i Then
                p.Width -= 10
                p.Left += 5
                If p.Width < 7 Then
                    i = False
                End If
            Else
                Me.p.BackgroundImage = actualpic
                p.BackgroundImageLayout = ImageLayout.Stretch
                Me.p.Width += 10
                Me.p.Left -= 5
                If Me.p.Width >= 50 Then
                    i = True
                    fac = True
                    cnt += 1
                    t.Stop()
                End If
            End If

        Else
            If i Then
                p.Width -= 10
                p.Left += 5
                If p.Width < 7 Then
                    i = False
                End If
            Else
                Me.p.BackgroundImage = Nothing
                p.BackgroundImageLayout = ImageLayout.Stretch
                Me.p.Width += 10
                Me.p.Left -= 5
                If Me.p.Width >= 50 Then
                    i = True
                    fac = False
                    cnt -= 1
                    
                    t.Stop()
                End If
            End If

        End If



    End Sub
    Public Function getobj() As Panel
        Return p
    End Function
    Public Function getface() As Boolean
        If stat <> True Then
            Return fac
        Else
            Return False
        End If

    End Function
    Public Function getimgid() As Integer
        Return imid
    End Function
End Class

The Main Form Code
__________________________________________________________

Public Class Form1
    Dim p(20) As pic
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        Dim j As Single = 0
        For i = 0 To 19
            j += 0.5
            p(i) = New pic(Int(j), 50, 50)
            p(i).setpos(i * 52, 5)
            Me.Controls.Add(p(i).getobj)
        Next

    End Sub

    Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        If pic.cnt > 1 Then
            Dim two(2) As Integer
            Dim j As Integer = 0
            For i As Integer = 0 To 19
                If p(i).getface Then
                    'p(i).faceoff()
                    two(j) = p(i).getimgid
                    j += 1
                End If
            Next
            If two(0) = two(1) Then
                For i As Integer = 0 To 19
                    If p(i).getface Then
                        p(i).setStat()
                        pic.cnt = 0
                    End If
                Next
            Else
                For i As Integer = 0 To 19
                    If p(i).getface Then
                        p(i).faceoff()
                    End If
                Next
            End If
        End If
    End Sub
End Class

Hope this will solve your problem.........

Thanks for the responses! I haven't had a chance to try them out yet but I will be working on my VB stuff tomorrow night and I'll you all know how it goes.

Thanks Kingsonprisonic. Your project is a huge help. There are a couple of things I don't fully understand though.

Firstly, I can see where the method in Timer_Tick1 is doing the comparison. But what's all the jazz with the heights and widths? Is that what causes your card flips to look animated? Similarly is that the reason for all the boolean fields in the pic class? I'm not fully clear on the purpose of i and fac; stat seems like it's used for signifying a match.

Big thanks though. This was super helpful, when I'm done I'll post my final solution so you can see (if you're interested) how I used what you demonstrated in your program.

This question has already been answered. Start a new discussion instead.