locked
Random RRS feed

  • Question

  • Is there a code to make sure that if i am generating random numbers with the random function that every number won't appear for more than two times ?
    Tuesday, February 23, 2016 5:02 AM

Answers

  • Essentially there is little difference between Dim and Private.  You can only use Dim (not Private) within a method but you can user either at module level.  If you want the full picture you can read all about it here and here.

    The game logic is very simple - the user clicks on a box and the image is displayed.  They then click on another box and it's image is displayed.  If the images match they remain - if not then after a short delay they disappear and the user tries again.

    The delay before the images are cleared will be determined by a timer so add a timer to your form and set its interval to about 1/2 second (you set it in milliseconds)

    In order to clear non matching images you need to remember which two boxes the user clicked so declare two variables at the top of your code (i.e. with module scope) of type PictureBox which will be used to store the boxes you click on.

    In order to keep track of where you are in the game you need to know whether or not the user is clicking on the first box or the second box.  That can be put another way - either the user is clicking on the first box or he isn't.  Which is clearly a binary choice and so you can use a Boolean variable to store this which should also be declared at the top of the code.

    In the PictureBox click handler add code to do the following:

    • Display the image in the box clicked on.
    • Set the boolean variable to indicate if this is the first or second box.
    • Depending upon whether this is the first or second box assign the clicked box to one of the two variables which store which boxes you have clicked on.
    • If this is the first box then no more to be done.
    • If this is the second box then compare the images, referencing the images through the two variables mentioned above.
    • If the images match then no more to be done.
    • If the images don't match then start a timer which will clear them both after a short delay

    Then in the timer's tick event handler you need to add code to:

    • Stop the timer.
    • Clear the two PictureBox images by setting the Image property to Nothing.

    And that is it - with less than 20 lines of code you have a working game.

    Obviously it needs some additions but they are easy once you have the bare bones of it working.

    Determining when the game is complete can be as simple as keeping a count of how many boxes are displaying images and telling the user when they are all done.

    Restarting the game is easy just clear the counter and create and fill a new list of boxes and assign the images to them.

    You will also need to handle the situation where the user clicks on the same box twice.

    And what happens if the user is quick and clicks on another box while the timer is still running.  Any issues there need to be handled as well.

    Going back to earlier questions:

    Breakpoints and stepping through the code are basic debugging techniques which you must learn if you are to successfully write code.  I'm amazed your teacher hasn't covered this.

    To set a breakpoint you can click on the grey bar to the left of the code opposite the line where you want the breakpoint.  This will create a brown(ish) circle on the bar and highlight the line.  Then when you run the code it will stop running when it gets to that line and you can investigate the state of your variables.

    Once the program has stopped at a breakpoint you can then single step through the following code by pressing F8 (or F10 or F11 - Microsoft in their wisdom seem to keep changing it).

    Both of these are on the Debug menu and so you can see the keyboard shortcuts on there against Debug | StepInto and Debug | Toggle Breakpoint.




    • Edited by Dave299 Wednesday, March 2, 2016 1:25 PM
    • Marked as answer by Peanut123 Thursday, March 3, 2016 12:29 AM
    Wednesday, March 2, 2016 1:12 PM

All replies

  • No, numbers generated with the Random function can repeat itself. What you trying to implement?

    Fouad Roumieh

    • Proposed as answer by Cor Ligthert Tuesday, February 23, 2016 7:38 AM
    Tuesday, February 23, 2016 5:15 AM
  • Is there a code to make sure that if i am generating random numbers with the random function that every number won't appear for more than two times ?

    Your description states the problem as more complicated than it needs to be.  You need to generate random numbers so each one is unique.  Then, each random number you generate is used two times.

    If you state your problem like that, then you can use the code you already have for generating unique random numbers.

    Tuesday, February 23, 2016 7:01 AM
  • Is there a code to make sure that if i am generating random numbers with the random function that every number won't appear for more than two times ?

    The solution is probably easier if the interval of random numbers is limited, for example integers between 1 and 1000. Is it limited?

    Tuesday, February 23, 2016 7:29 AM
  • In addition to the others, 

    Nothing in the world is real unique for sure not a single number, if you want to make it a little bit unique, you can add a signature/ (Be aware to get that real unique, then current computers have not yet facilities for that.) 

    (However, in fact it means that the number should be encapsulated in an object, which contains the unique signature.)


    Success
    Cor


    Tuesday, February 23, 2016 7:44 AM
  • you could make two lists of numbers
    List #1 is just numbers from 0 to your upper limit
    List #2 is the same size as #1m but is all zeros

    generate a random number that will be the index to look at (0 to list.count)

    if list2 at that index is 0 then use the number in list1 at the index and mark list 2 at the same index with a 1

    if list2 at that index is 1 then use the number in list1 at the index then remove from both lists at the location specified by the index.


    Wednesday, February 24, 2016 3:54 PM
  • I'm trying to place 16 picture box randomely by using  the tag property and a random generator of numbers 1 to 8 ?
    Thursday, February 25, 2016 2:33 AM
  • Do you mean you are trying to place 16 pictures randomly into 8 boxes?

    Solitaire

    Thursday, February 25, 2016 2:52 AM
  • No I don't i have to place 8 pairs of images into 16 boxes. I would like to start by box 1, then by box 2, box 3... (at box 3 and more, i have to check to mae sure the random number wasn't already generated twice. if it was, then the random has to generate another number. I would like to do this by tagging my images, but i don't know how...)
    Thursday, February 25, 2016 2:59 AM
  • could somebody please explain very precisely what i need to do? I just know how to tag the images.
    Thursday, February 25, 2016 3:00 AM
  • could somebody please explain very precisely what i need to do? I just know how to tag the images.
    Are you adding these PictureBoxes inside a loop or based on user action? I'm asking because if its inside the loop you can simply create a counter. Why do you want to check only from number 3 what if one and two were duplicate. Will it work for you to create an Int List object that holds the generated number and then you can search that list for duplicates?

    Fouad Roumieh

    Thursday, February 25, 2016 7:27 AM
  • i have to check to mae sure the random number wasn't already generated twice. if it was, then the random has to generate another number.

    There is no need to check if the random number was already generated twice. 

    Just think about how the backstage hands set up the board between each round.  They don't start at square one and then try to fill each square.   They start with a stack of picture cards :  dog dog cat cat mouse mouse owl owl cow cow horse etc ...

    In fact, the order doesn't matter, just so long as it is a pile of 16 cards with 8 different images.

    Then they look at the board and choose a random square.  IF the square doesn't already have a card on it, they pick the top card off the stack and place it on the square, face down.  If it already has a card on it, they pick another random square, until they pick an empty one.  They repeat that for each card until there are no more cards left in the stack.


    • Edited by Acamar Thursday, February 25, 2016 8:54 AM sp
    Thursday, February 25, 2016 8:53 AM
  • You need to use a shuffle-sort algorithm to randomly generate 16 numbers to an array representing your picture boxes.  Then use integer division to divide the results by 2 and save the divided result to another array representing your images. 

    Here is the code using a Console application and saving it to two integer arrays.  When you run the program, you can see the output which results in 16 random numbers between 1 and 8, with exactly 2 of each number in random order.  Every time you run the program, you will see a different random output.

    You will have to adapt the code to assign images into the randomized order of the img() array.  Then place those images into your tagged picture boxes in that randomized order.

        Sub Main()
            Dim mix, temp As Integer
            Dim num As Integer = 16
            Dim randnum As New Random()
            Dim box(num) As Integer
            Dim img(num) As Integer
            For x As Integer = 1 To num
                box(x) = x
            Next x
            For x As Integer = num To 1 Step -1
                mix = randnum.Next(x, num + 1)
                temp = box(mix)
                box(mix) = box(x)
                box(x) = temp
            Next x
            For x As Integer = 1 To num
                img(x) = ((box(x) + 1) \ 2)
                Console.WriteLine(img(x))
            Next x
            Console.ReadLine()
        End Sub



    Solitaire




    • Edited by Solitaire Thursday, February 25, 2016 5:43 PM
    Thursday, February 25, 2016 5:36 PM
  • With GUID and Linq this is quite easy.

    Code to create list of numbers:

            Dim rsn As New List(Of RandomNumbers)
            For i = 1 To 16
                Dim rn As New RandomNumbers With {.theNumber = i, .theGUID = Guid.NewGuid}
                rsn.Add(rn)
            Next
    
            Dim rsSorted As List(Of RandomNumbers) = (From r In rsn Select r Order By r.theGUID).ToList
    

    RandomNumbers Class:

    Public Class RandomNumbers
        Public Property theNumber As Integer
        Public Property theGUID As Guid
    End Class
    Then you can simply use the list as list of random numbers using the theNumber property of the class.


    Lloyd Sheen

    Thursday, February 25, 2016 10:36 PM
  • can you tell me what i did wrong please

        Dim GenerateurHasard As New Random()
        Dim boxes As New List(Of PictureBox)
        Dim images As New List(Of Image)
        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            Dim i As Integer, J As Integer, Compteur As Integer, Testpasse As Boolean
            Dim Tableau(16) As Integer
            For i = 1 To 16
                Tableau(i) = vbNull
            Next i
    
            Randomize()
            For i = 1 To 16
                MsgBox(i)
                Testpasse = False
                Do Until Testpasse
                    Tableau(i) = CInt(Int((8 * Rnd()) + 1))
                    MsgBox("Valeur teste" & Tableau(i))
                    Compteur = 0
                    For J = 1 To 16
                        MsgBox("J=" & J)
                        If Tableau(i) = Tableau(J) Then Compteur = Compteur + 1
                    Next J
                    If Compteur < 3 Then
                        Testpasse = True
                    Else
                        Testpasse = False
                    End If
                    MsgBox(Testpasse)
                Loop
            Next i
    
            images(1) = My.Resources.pic1
            images(2) = My.Resources.pic2
            images(3) = My.Resources.pic3
            images(4) = My.Resources.pic4
            images(5) = My.Resources.pic5
            images(6) = My.Resources.pic6
            images(7) = My.Resources.pic7
            images(8) = My.Resources.pic8
    
            For i = 1 To 16
                boxes(i).Image = images(Tableau(i))
            Next i
    
    
            images.Add(My.Resources.pic1)
            images.Add(My.Resources.pic2)
            images.Add(My.Resources.pic3)
            images.Add(My.Resources.pic4)
            images.Add(My.Resources.pic5)
            images.Add(My.Resources.pic6)
            images.Add(My.Resources.pic7)
            images.Add(My.Resources.pic8)
    
    
    
            Dim numero As Integer 'créer une variable qui contrôle quelle image est affichée
    
            boxes(numero).Visible = False
    
            'numero = GenerateurHasard.Next(1, 16) 'valeur de nouveau image à afficher
    
            ''afficher l'image selon le numéro generé au hasard
            'If (numero = 1) Then
            '    PictureBox1.Visible = True
            'End If
            'If (numero = 2) Then
            '    PictureBox2.Visible = True
            'End If
            'If (numero = 3) Then
            '    PictureBox3.Visible = True
            'End If
            'If (numero = 4) Then
            '    PictureBox4.Visible = True
            'End If
            'If (numero = 5) Then
            '    PictureBox5.Visible = True
            'End If
            'If (numero = 6) Then
            '    PictureBox6.Visible = True
            'End If
            'If (numero = 7) Then
            '    PictureBox7.Visible = True
            'End If
            'If (numero = 8) Then
            'PictureBox8.Visible = True
            'End If
            'If (numero = 9) Then
            '    PictureBox9.Visible = True
            'End If
            'If (numero = 10) Then
            '    PictureBox10.Visible = True
            'End If
            'If (numero = 11) Then
            '    PictureBox11.Visible = True
            'End If
            'If (numero = 12) Then
            '    PictureBox12.Visible = True
            'End If
            'If (numero = 13) Then
            '    PictureBox13.Visible = True
            'End If
            'If (numero = 14) Then
            '    PictureBox14.Visible = True
            'End If
            'If (numero = 15) Then
            '    PictureBox15.Visible = True
            'End If
            'If (numero = 16) Then
            '    PictureBox16.Visible = True
            'End If


    • Edited by Peanut123 Thursday, March 3, 2016 2:38 PM
    Sunday, February 28, 2016 5:07 PM
  • can you tell me what i did wrong please


    What you are doing wrong is ignoring all the advice you have already been given.

    I gave you a working solution for this over two weeks ago and others have provided other guidance.  You appear to be ignoring it all.

    Even if you don't want to use my complete solution it shows you a way of assigning images to the pictureboxes which you could extract.


    • Edited by Dave299 Sunday, February 28, 2016 5:22 PM
    Sunday, February 28, 2016 5:20 PM
  • You have so much redundant code, it's ridiculous.  You should be using an array for your images, and place them in loops.  That would reduce your code to a fraction of what it is now.

    Solitaire

    Sunday, February 28, 2016 5:53 PM
  • I think if you just sit and look at your code you will notice how redundant it is, so the first step is to look at it again and try to clean it up, here are some tips:

    • For example you can simply check If (J=1 And number=1) then set the image for square1 and square2...ect in the same If block.
    • Your whole code is sitting behind the button click event handler, try to create Function like SetImages() and call those functions from inside the button click, same as you did with Randomize().
    • You can connect multiple events to one event handler so you don't repeat it as your code:
    • http://stackoverflow.com/questions/13323397/how-to-handle-multiple-click-events-with-same-sub

    I don't know what do you mean by "what i did wrong with this code", is it not working as expected or what?

    You started with a very generic question and now its expanding (from my side till now I don't know what help do you need), you need to be a bit accurate about the issue you are facing to get quicker assistance.


    Fouad Roumieh

    Sunday, February 28, 2016 6:45 PM
  • Ok I cleaned it up abit i think. I'm having a lot of trouble with the random aspect of things and also i have to write a serie of ifs (but where in my code, and also, how do i write it). I understand that if the two picture boxes on which you click have the same picture, they stay, if not they don't...
    Sunday, February 28, 2016 6:54 PM
  • I'm having a lot of trouble with the random aspect of things and also i have to write a serie of ifs (but where in my code, and also, how do i write it).

    That's because you still do not have your procedure sorted out.  You should not be writing code.  You should be writing a proper description of what you are trying to do - a step-by-step description, in plain language, of the process that you will go through and the result that you will get.   When you have that, you can write the code to do it.

    You have collected bits and pieces of code from different places and simply strung them together without any overall understanding of the steps you procedure you need to go through.

    • Edited by Acamar Sunday, February 28, 2016 9:14 PM sp
    Sunday, February 28, 2016 9:11 PM
  • Ok i've tried to simplify it some more but it doesn't work yet the tops come off at a click when the timer is on but the images Under don't appear. I actually have 32 picture boxes(the covers, and the ones Under which are assigned images at random). Iknow my code is redudant, but it doesn't bother me.

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Dim GenerateurHasard As New Random() Dim boxes As New List(Of PictureBox) boxes.Add(PictureBox1) boxes.Add(PictureBox2) boxes.Add(PictureBox3) boxes.Add(PictureBox4) boxes.Add(PictureBox5) boxes.Add(PictureBox6) boxes.Add(PictureBox7) boxes.Add(PictureBox8) boxes.Add(PictureBox9) boxes.Add(PictureBox10) boxes.Add(PictureBox11) boxes.Add(PictureBox12) boxes.Add(PictureBox13) boxes.Add(PictureBox14) boxes.Add(PictureBox15) boxes.Add(PictureBox16) Dim images As New List(Of Image) images.Add(My.Resources.pic1) images.Add(My.Resources.pic2) images.Add(My.Resources.pic3) images.Add(My.Resources.pic4) images.Add(My.Resources.pic5) images.Add(My.Resources.pic6) images.Add(My.Resources.pic7) images.Add(My.Resources.pic8) Private Sub Top1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Top1.Click If Timer1.Enabled = False Then Top1.Visible = True Else : Top1.Visible = False End If End Sub Private Sub Top2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Top2.Click If Timer1.Enabled = False Then Top2.Visible = True Else : Top2.Visible = False End If End Sub

    Private Sub Top3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Top2.Click If Timer1.Enabled = False Then Top3.Visible = True Else : Top3.Visible = False End If End Sub

    Private Sub Top2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Top2.Click If Timer1.Enabled = False Then Top4.Visible = True Else : Top4.Visible = False End If End Sub

    Private Sub Top2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Top2.Click If Timer1.Enabled = False Then Top5.Visible = True Else : Top5.Visible = False End If End Sub(It continues)





    • Edited by Peanut123 Tuesday, March 15, 2016 3:13 AM
    Monday, February 29, 2016 2:05 AM
  • By the way you were really right i wrote every step down on paper and i now understand every step much better. Thank you again for all your help !
    Monday, February 29, 2016 2:06 AM
  • Ok i've tried to simplify it some more but it doesn't work yet the tops come off at a click when the timer is on but the images Under don't appear.

    You still have far too much repeated code.  Go back to some of the first advice you had - put the pictureboxes into a list and process them by iterating over the list.

    Monday, February 29, 2016 2:15 AM
  • How can i iterate over the list ?
    Monday, February 29, 2016 2:23 AM
  • I know how to put the pictureboxes into a list but where exactly in my code should i put it? Also, even though it's still redundant is it better at all or it still doesn't make any sense to you ?
    Monday, February 29, 2016 2:25 AM
  • I initially considered using this but wasn't sure how to use it.
    boxes(0) = Square1
    '        boxes(1) = Square2
    '        boxes(2) = Square3
    '        boxes(3) = Square4
    '        boxes(4) = Square5
    '        boxes(5) = Square6
    '        boxes(6) = Square7
    '        boxes(7) = Square8
    '        boxes(8) = Square9
    '        boxes(9) = Square10
    '        boxes(10) = Square11
    '        boxes(11) = Square12
    '        boxes(12) = Square13
    '        boxes(13) = Square14
    '        boxes(14) = Square15
    '        boxes(15) = Square16
    
    '        images.Add(My.Resources.ballon)
    '        images.Add(My.Resources.soulier)
    '        images.Add(My.Resources.poisson)
    '        images.Add(My.Resources.arcenciel)
    '        images.Add(My.Resources.parapluie)
    '        images.Add(My.Resources.soleil)
    '        images.Add(My.Resources.soulier)
    '        images.Add(My.Resources.banane)
    '        images.Add(My.Resources.ballon)
    '        images.Add(My.Resources.soulier)
    '        images.Add(My.Resources.poisson)
    '        images.Add(My.Resources.arcenciel)
    '        images.Add(My.Resources.parapluie)
    '        images.Add(My.Resources.soleil)
    '        images.Add(My.Resources.soulier)
    '        images.Add(My.Resources.banane)

    Monday, February 29, 2016 2:34 AM
  • Ok  my new code is better and but i tried replacing the icons by images cuz i have images but it didn't work
            For Each image In boxes.Controls
                Dim image = TryCast(control, image)
                If image IsNot Nothing Then
                    Dim randomNumber = random.Next(boxes.Count)
                    image.Image = boxes(randomNumber)
                    image.Tag = boxes(randomNumber)
                    image.RemoveAt(randomNumber)
                End If
            Next

    didn't work everywhere.

    • Edited by Peanut123 Tuesday, March 15, 2016 3:19 AM
    Monday, February 29, 2016 4:56 PM
  • I'll give you one thing to make your code easier to read.  I bet it wasn't the most fun to change each of the 16 routines for a button click.  You can consolidate these methods into one method which is much easier to maintain and easier to read.  Remember that 90% of programming is pattern recognition.

    Private Sub Top16_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TheButton.Click
    	Dim but as button = Ctype(sender,Button)
            If Timer1.Enabled = False Then
                but.Visible = True
            Else 
    	    but.Visible = False
            End If
    End Sub
    you will also have to change the click event name for each button but your code will be better using this method.  Remember if code looks the same that you input more than once it is a candidate for seeing the similarities rather than the differences. 


    Lloyd Sheen

    Monday, February 29, 2016 8:43 PM
  • I know how to put the pictureboxes into a list but where exactly in my code should i put it? Also, even though it's still redundant is it better at all or it still doesn't make any sense to you ?

    Declare the list of controls at the form level.  Load the controls into the list in the form load event. Use a loop wherever you currently have a list of identical code, eg
    For I As Integer = 0 To 15
        Top(I).Visible) = False
    Next I

    Use that list of controls to avoid having to search through all controls:
            For Each control In TableLayoutPanel1.Controls
                ...

    You have a separate event handler for each click event. As the code is always the same, you only need one event handler.

    You are using If statements when a simple assignment will do:

            If Timer1.Enabled = False Then
                Top14.Visible = True
            Else : Top14.Visible = False
            End If

    You have written out your procedure in plain language, but you haven't posted it here, so it's not possible to say whether the procedure will work or not, or whether you code matches the procedure.

    Monday, February 29, 2016 9:22 PM
  • Ok so I have now done what sqlguy suggested. It's so much simpler ! I know you all must find me pretty crazy for repeating my code like 16 times... Anyways thank you ! Ok now here were the things I wrote down on my paper :

    1. Create a timer. That timer will start at 1000 and count down to 0. The number of seconds left will be written in a label.

    2. Create the start button. If the timer isn't on, we put it on and the start button will say "pause". If it's already on, we put it off and the start button will say "start". When we click on the button, the images will be assigned to the labels in the table panel layout. Then we play the game, and we can win so the code has to check for that. When we press on in all the top pictureboxes hide the labels.

    3. Assign the images. Create a list with 16 images (8 pairs of images). This is where i have some trouble. For each label in the tablelayoutpanel, a randomnumber from 1 to to  number of items in the image list which is 16 is generated. That number is linked to an image in that list. Here, i don't know how to make the image appear (I took this part from a website, but that website used icons so it was text but i'm using images please help me ).

    4. Check if the user won. For each label in the tablelayoutpanel, the computer has to check wether an image is assigned to it. (I'm not sure if it will work for the last pair?). If all the labels have been assigned an image, then a message congratulates the user.

    5. Top pictureboxes. At the beginning, these 16 top pictureboxes hide all of the labels in the tablelayoutpanel. If the timer is on, so the user is playing, when he click on a top picture box, it disappears. If the timer is off, the top picture box doesn't disappear it stays there to cover the labels Under.

    6. Labels in the tablelayoutpanel. I have a lot of trouble with this too but basically when a label is clicked a picture will appear. Then user clicks two labels at a time. If the image in the first label is the same as the image on the secon label clicked, then they stay. If they aren't the same, then the top boxes come back to cover them (you first have to click the top picture box, then the label in the tablelayoutpanel to see an image).

    Monday, February 29, 2016 11:55 PM
  • I need help for 6. too please
    Monday, February 29, 2016 11:55 PM
  • Ok now here were the things I wrote down on my paper :

    3. Assign the images. Create a list with 16 images (8 pairs of images). This is where i have some trouble. For each label in the tablelayoutpanel, a randomnumber from 1 to to  number of items in the image list which is 16 is generated. That number is linked to an image in that list. Here, i don't know how to make the image appear (I took this part from a website, but that website used icons so it was text but i'm using images please help me ).

    Step 3 comes first.  You should not move onto the other steps until it is complete and tested.

    3. Assign the images. Create a list with 16 images (8 pairs of images).

    Why?  You are jumping to the solution before you know what you want to achieve.  The description should be I will have a board on which 8 pairs of images will be displayed.  I need to access these images to display them.  That leads to a possible step in the solution: I will create a list of the 8 images (each image is used twice).  The list of images can be created by reading them from a file, or fetching them from resources - you need to decide which.  You can stop and test your code at this point.

    For each label in the tablelayoutpanel,

    TableLayoutPanel has not been mentioned in your description.  That is going to enormously complicate things.  I presume it is used to aid in resizing the form.  If so, it can be left to the very end of your development - for now, work with a fixed-size form.  This step should be:

    I need to display 16 images, so I will use 16 labels.  I will create the 16 labels using the Designer, and I will write code in the form load event to put those 16 labels, in order, into a List.

    Labels is an odd choice, but it is easily changed later.

    a randomnumber from 1 to number of items in the image list which is 16 is generated.

    Why?  Again, you have made an assumption about what you need to do without spelling out the reason for doing it.  Your task description at this point should be I need to assign images from the image list (in pairs) to labels in the label list, in random order.

    That number is linked to an image in that list.

    That's what you need to do, but how?   The result will be that each label in the label list will have a number 'linked' to it, indicating which image from the image list it is displaying. Each image number will appear twice.

    i don't know how to make the image appear

    Jumping the gun.  How are you going to 'link' each image to two of the labels? (Note that, so far, this is probably a perfectly adequate approach - but you need some description of how you are going to do this.  There are several different options - you need to choose one.  For instance 'An array of 16 elements will be created, where the array index indicates the label, and the number at that index indicates the image to display in that label'.

    Write out an example -
    (0,5),(1,7),(2,6),(3,2),(4,0),(5,6),(7,2)...(14,3),(15,5) so you have something to test the code against when you write it.  That means label(0) will display image(1), label(1) will display image(7), label(2) will display image(6) and so on.

    This is the only tricky part so far, but you already have several examples.  The process to create this linking array is :

    Create a temporary list of sequential numbers from 0 to 15.
    For I = 0 to 7 (that is, for the index of each image in the image list)
        Calculate a random number (X) from 0 to the number of items left in the temporary list.
        Set linking array element at index X to the value I
        Remove item X from the temporary list
        Calculate a random number (X) from 0 to the number of items left in the temporary list.
        Set linking array element at index X to the value I
        Remove item X from the temporary list

    You can stop and test your code at this point.

    Now you have your array, you can display the images. They should display in random order. Because you have done the preliminary work carefully, this is really easy.

    For I = 0 to 15
        Labels(I).Image = Images(Linking(I))

    That is, 'the image to be displayed in label I is the image whose index in the images list is the value from the linking array at index I'.


    • Edited by Acamar Tuesday, March 1, 2016 2:40 AM sp
    Tuesday, March 1, 2016 2:37 AM
  • Ok thank you I will try. And I wanted to use picture boxes but on that website they used labels in a tablelayoutpanel and I didn't know how to say for each control in tablelayoutpanel.controls but for pictureboxes...
    Tuesday, March 1, 2016 12:18 PM
  • Or should I use buttons?
    Tuesday, March 1, 2016 12:27 PM
  • Or should I use buttons?


    No - you want to display images so use PictureBoxes - you don't need buttons or labels.

    This is what I posted to you over two weeks ago:

    "Revisting my original suggestion it isn't necessary to pick images randomly and pick boxes randomly.  Simply going through the image list in order and assigning to two boxes at random will suffice.

    So in pseudo code:

    For Each Image in the list of images
        Pick a Box at random from the list
        Assign the image to the box
        Remove that box from the list(so it doesn't get chosen twice)    
        Pick another box at random
        Assign the image to the box
        Remove that box from the list

    If you assign the images to the Image property of the PictureBoxes then obviously all the images will be visible at the start which rather defeats the object of the game.  So you could use the Tag property to store the images and only display them when the box is clicked.

    Try coding the routine above and post back.  Initially assign the images to the Image properties of the boxes, that will let you check that the routine is working as you will see the images.  Once you are happy that it is working change it so that the image is stored in the Tag property instead.

    Study the help for the Random class Next method carefully - take note of which parameters are inclusive and which are exclusive."

    Acamar is now trying to guide you in much the same direction but I think my suggestion is actually simpler.  Assigning images directly to the image property of a picturebox will let you see the images and so you can tell easily if your code is working.  Once you are happy with that just change the code to assign the images to the Tag property and they won't be seen when the game starts but each image will still be associated with a Picturebox.  To display an image in the Picturebox click event handler simply copy the image from the Tag to the Image property and it will be displayed.

    If you actually try to do what has been suggested and post back with just that part you will get better help than if you keep posting huge amounts of largely irrelevant code.

    Tuesday, March 1, 2016 12:42 PM
  • Ok I will try thank you very much. But I don't exactly understand how to use the tag? I just have to write come thing in each picture box's tag, and then I can use it in my code? And also when you say assign images to the image property of the picture box is it how acamar suggested in the last few lines? And lastly what do you mean by copy the image from the tag?
    Tuesday, March 1, 2016 1:34 PM
  • The Tag is just a property which every control has.  It is of type Object and you can assign anything to it.  It is very useful if you want to associate an object with another object.  In your case you want to associate an image with each picturebox.

    So if PB is your PictureBox and Img is your Image then you assign it to the Tag with:

    PB.Tag = Img

    To assign an image to the PictureBox's Image property you would use

    PB.Image = Img

    Can you work out how to copy from the Tag to the Image.

    Also you are only going to get more confused if you try and run with two threads covering much the same problems.  As the other thread is marked as answered it would be better to advise those helping in the other thread to join this one.


    • Edited by Dave299 Tuesday, March 1, 2016 2:11 PM
    Tuesday, March 1, 2016 2:08 PM
  • Ok so i've written this up to now. I Don't know how to write how to pick a box at random and then assign the image to it. I understand though how the tags work...
            Dim ListofImages =
                    New List(Of Image) From {My.Resources.banane, My.Resources.banane, My.Resources.poisson, My.Resources.poisson, My.Resources.arcenciel, My.Resources.arcenciel, My.Resources.ballon,
                                             My.Resources.ballon, My.Resources.soulier, My.Resources.soulier, My.Resources.poule, My.Resources.poule, My.Resources.soleil, My.Resources.soleil,
                                             My.Resources.parapluie, My.Resources.parapluie}
    
            Dim ListofBoxes =
                    New List(Of PictureBox) From {PictureBox1, PictureBox2, PictureBox3, PictureBox4, PictureBox5,
                                                  PictureBox6, PictureBox7, PictureBox8, PictureBox9, PictureBox10,
                                                  PictureBox11, PictureBox12, PictureBox13, PictureBox14, PictureBox15,
                                                  PictureBox16}
    
            For Each Image In ListofImages
                Dim NumberofPB = TryCast(Image, PictureBox)
                ListofBoxes.RemoveAt(NumberofPB)
            Next

    Tuesday, March 1, 2016 7:14 PM
  • To pick a box at random you use an instance of the Random class. 

    That class has a Next method which produces the next integer number in a pseudo random sequence.  It takes two arguments, the first being the lowest number it can produce and the second being the highest number it can produce +1.

    So for instance:

          Dim Rnd As New Random
          Dim Number As Integer = Rnd.Next(100, 200)

    will assign to the variable number a value chosen at random between 100 and 199.

    So you want to choose values which are within the range of indeces of your list of pictureboxes (hint - you may think that because you have 16 boxes then you just use 16 for the second argument.  But think what happens if you decide to modify the game to use 25 boxes instead and also what happens when you remove the boxes which have been assigned from the list.)


    • Edited by Dave299 Tuesday, March 1, 2016 7:32 PM
    Tuesday, March 1, 2016 7:30 PM
  • Ok I tried to rewrite it again. I did the opposite of what you told me to do but hopefully it is still acurate. What do you think ?

    For Each PictureBox In ListofBoxes 'Pour chaque picturebox du dessous

    Dim WhichImageInList As Integer

    WhichImageInList = Random.Next(ListofImages.Count)

    PictureBox.Image = ListofImages(WhichImageInList)

    ListofImages.RemoveAt(WhichImageInList)

    Next




    • Edited by Peanut123 Thursday, March 3, 2016 2:43 PM
    Tuesday, March 1, 2016 7:34 PM
  • Well that's getting closer.

    Have you declared an instance of Random.  If so calling it Random is not good practice, use a different name.

    The reason for picking the boxes at random instead of the images is that you need to use each image twice so having picked an image at random you then need to pick two boxes at random before removing the image and both boxes from their lists.

    If you just loop through all the images and assign each one to two random boxes (removing the boxes from the list as you go) you will find it a lot easier.

    So set up a loop to go through each image in the list.  Within that loop use codes similar to what you have to assign each image to two boxes.

    Tuesday, March 1, 2016 7:47 PM
  • Yes, I declared Random as new random at the very beginning. I just tested my code though, and it seems to work fine. I don't understand why what i wrote wouldn't work, i just take out an image of the list when it's randomely assigned and it works because i have two times each image in my list. I know it's probably much more complicated but it was pretty hard for me (i'm a beginner, as you probably know). Do you think i could keep this code?
    Tuesday, March 1, 2016 8:32 PM
  • Ok - I hadn't spotted that you had put each image into the list twice.

    In that case your code is ok.

    Provided that you are seeing all 16 boxes filled with images with each one showing twice then change the code to assign the images to the Tag property and then write the code to show the image when you click on a picturebox.  This only needs one method - you don't need to write similar code for every picturebox.

    Tuesday, March 1, 2016 9:30 PM
  • So this would be ok for the tag property (i only changed the .image to .tag) ?

            PictureBox.Tag = ListofImages(WhichImageInList) 'L'image du picturebox sera déterminée par le nombre 1 à 16
    


    • Edited by Peanut123 Thursday, March 3, 2016 3:31 AM
    Tuesday, March 1, 2016 11:11 PM
  • And also to show the image when i click on a picture box is it an IF ?
    Tuesday, March 1, 2016 11:12 PM
  • Never mind that question it was pretty stupid as you can see... Anyways, would this be ok ? PictureBox.Image = PictureBox.Tag
    • Edited by Peanut123 Thursday, March 3, 2016 3:32 AM
    Tuesday, March 1, 2016 11:15 PM
  • I just tried to make it play and at the place where i changed the .image to .tag it says a "NullReferenceException was unhandled". Did I do Something wrong ? If so, is it in my code or do I need to write Something in the picturebox's tag in the designer ?
    Tuesday, March 1, 2016 11:18 PM
  • Never mind that question it was pretty stupid as you can see... Anyways, would this be ok ?

    Don't use the Tag property for the images - the Picturebox control has it's own image properties that are usable for this purpose. The Tag property is an Object and can only be used after it is cast to the correct type.

    The default image (the back of the card) should be the error image.
    https://msdn.microsoft.com/en-au/library/system.windows.forms.picturebox.errorimage(v=vs.110).aspx

    and the random allocated image should be the initial image.
    https://msdn.microsoft.com/en-au/library/system.windows.forms.picturebox.initialimage(v=vs.110).aspx

    To turn all the cards face down use

            For Each PB As PictureBox In ListofBoxes
                PB.Image = PB.ErrorImage
            Next
    

    and to turn a selected card face up use

            ListofBoxes(I).Image = ListofBoxes(I).InitialImage
    Tuesday, March 1, 2016 11:26 PM
  • There is nothing wrong with assigning the images to the Tag property.  If you are getting a null reference exception then it means the PictureBox you are clicking on has not had its Tag property set properly.

    When you were assigning the images to the Image property where you seeing all 16 PictureBoxes filled correctly?

    Wednesday, March 2, 2016 12:23 AM
  • Yes i was.
    Wednesday, March 2, 2016 12:25 AM
  • But i didn't set anything in the picture box's tag property. What should i write ?
    Wednesday, March 2, 2016 12:26 AM
  • But i didn't set anything in the picture box's tag property. What should i write ?
    Don't use the tag property.   It is not suitable for this purpose.  The Picturebox control has two additional image properties that will do what you need.
    Wednesday, March 2, 2016 12:28 AM

  • Don't use the tag property.   It is not suitable for this purpose.

    Rubbish!

    It is being used as a means of assigning an image to the picturebox without displaying it.  The fact that the property is of type Object is irrelevant.

    This is precisely the sort of use for which it was intended, to quote msdn:

    "A common use for the Tag property is to store data that is closely associated with the control"

    • Edited by Dave299 Wednesday, March 2, 2016 12:37 AM
    Wednesday, March 2, 2016 12:34 AM
  • I actualy like the idea of the tag it seems more simple
    Wednesday, March 2, 2016 12:38 AM
  • I can't understand what you were doing wrong at the moment.  If all pictureboxes were having their images set correctly then changing the assignment from Image to Tag should not have caused an error.

    Can you post a screenshot of the error?

    Wednesday, March 2, 2016 12:51 AM
  • Wednesday, March 2, 2016 12:58 AM
  • Hmmm - that makes no sense at all.

    You say you don't get the error if that line reads:

    PictureBox.Image = Images(WhichImageInList)

    and you are sure you haven't changed anything else?

    If you hover your mouse over each part of the line you should see a pop up showing the values of each part of the expression - which part is showing 'Nothing'.  Note that the Tag will show Nothing as it hasn't been assigned yet.


    • Edited by Dave299 Wednesday, March 2, 2016 1:14 AM
    Wednesday, March 2, 2016 1:11 AM
  • You're right it doesn't work anymore with the .image either. When i hover over the PictureBox, it says "Nothing", and over the WhichImageInList "0"
    Wednesday, March 2, 2016 1:16 AM
  • That means your picturebox list has not been filled correctly.  Double check the code which does that.
    Wednesday, March 2, 2016 1:18 AM
  • Here it is

    Dim ListofImages = New List(Of Image) From {My.Resources.banane, My.Resources.banane, My.Resources.poisson, My.Resources.poisson, My.Resources.arcenciel, My.Resources.arcenciel, My.Resources.ballon, My.Resources.ballon, My.Resources.soulier, My.Resources.soulier, My.Resources.poule, My.Resources.poule, My.Resources.soleil, My.Resources.soleil, My.Resources.parapluie, My.Resources.parapluie} Dim ListofBoxes = New List(Of PictureBox) From {PictureBox1, PictureBox2, PictureBox3, PictureBox4, PictureBox5, PictureBox6, PictureBox7, PictureBox8, PictureBox9, PictureBox10, PictureBox11, PictureBox12, PictureBox13, PictureBox14, PictureBox15, PictureBox16} Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load compteur = 300 LabelCompteur.Text = compteur End Sub Private Sub BouttonDemarrer_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BouttonDemarrer.Click If (Not Timer1.Enabled) Then Timer1.Enabled = True BouttonDemarrer.Text = "Démarrer" Else Timer1.Enabled = False BouttonDemarrer.Text = "Redémarrer" Top1.Visible = True Top2.Visible = True Top3.Visible = True Top4.Visible = True Top5.Visible = True Top6.Visible = True Top7.Visible = True Top8.Visible = True Top9.Visible = True Top10.Visible = True Top11.Visible = True Top12.Visible = True Top13.Visible = True Top14.Visible = True Top15.Visible = True Top16.Visible = True LabelCompteur.Text = 0 End If AssignImagesToPictureBoxesWithTags() 'MemoryGame() 'CheckForWinner() End Sub Private Sub AssignImagesToPictureBoxesWithTags() Dim PBox As PictureBox Dim ListofBoxes = New List(Of PictureBox) From {PictureBox1, PictureBox2, PictureBox3, PictureBox4, PictureBox5, PictureBox6, PictureBox7, PictureBox8, PictureBox9, PictureBox10, PictureBox11, PictureBox12, PictureBox13, PictureBox14, PictureBox15, PictureBox16} Dim ListofImages = New List(Of Image) From {My.Resources.banane, My.Resources.banane, My.Resources.poisson, My.Resources.poisson, My.Resources.arcenciel, My.Resources.arcenciel, My.Resources.ballon, My.Resources.ballon, My.Resources.soulier, My.Resources.soulier, My.Resources.poule, My.Resources.poule, My.Resources.soleil, My.Resources.soleil, My.Resources.parapluie, My.Resources.parapluie} For Each PBox In ListofBoxes 'Pour chaque picturebox du dessous Dim WhichImageInList As Integer 'On va créer une variable qui représentera l'image choisie WhichImageInList = Random.Next(ListofImages.Count) 'Cette image sera générée au hasard par Random (entre 1 et 16) PBox.Image = ListofImages(WhichImageInList)

    ListofImages.RemoveAt(WhichImageInList) Next End Sub

    • Edited by Peanut123 Tuesday, March 15, 2016 3:27 AM
    Wednesday, March 2, 2016 1:21 AM
  • You must be clearing the entries somewhere else.  If the list was actually empty then the code where you are getting the error wouldn't be reached so the list must have null entries in it.

    Try setting a breakpoint on the line that creates the list and then step through (F8) the code to see if you can spot where it is going wrong.

    I am going to bed soon (it's 0130 here) so may not respond much longer.   But assuming you sort this issue out the next step is to display the images on clicking a picturebox.  To do that you need a handler for the click event.  To get that just double click one of the pictureboxes.  That will create an empty handler looking something like:

       Private Sub PictureBox1_Click(sender As System.Object, e As System.EventArgs) Handles PictureBox1.Click
    
       End Sub
    


    to that add handles clauses for the rest of the pictureboxes.

    You then need to determine which box has been clicked.  That information is contained in the sender parameter, which is of type Object so should be cast to the correct type of PictureBox. 

    Dim PB As PictureBox = CType(sender, PictureBox)

    You won't need the Ctype of you have Option Strict Off - you should have been advised to turn it on but if you haven't don't do it now - you've got enough problems already.

    Once you have determined which box has been clicked then copy the Tag property to the Image property.

    To clear an image you just set the Image property to Nothing.  You will do this with a timer if the user selects different images.

    Wednesday, March 2, 2016 1:38 AM
  • Ok I understand the following steps but i don't get what's wrong with my list of pictureboxes. What do you mean by clearing the entries ? What do you mean a null entry ? Also sorry but i have no idea how to create a breakpoint on the line and i don't even know what is F8 (I'm sorry you must be so fustrated at me right now)...
    Wednesday, March 2, 2016 1:46 AM
  • You are making it far harder than it needs to be.

    Get rid of all of that and modify the form design so you only have the 16 pictureboxes.

    In your declarations, for now, you only need the two lists and the random generator.

    In the form load event handler put the code which loads the images in to the pictureboxes (image first to prove it works and then change to tag).

    Presuming that works take it from there.

    I'm off!

    Wednesday, March 2, 2016 2:06 AM
  • @Peanut

    I have created a project which I think is where you are up to at the moment, see below.

    But before getting into that I have seen a flaw in what you have so far caused by your change to the way you fill the PictureBoxes (I knew I did it my way for a reason)

    The image list is being filled from images stored in your project resources and you are putting each image into the list twice.  Well that is what you think you are doing but in fact you are actually putting 16 different images into the list.

    When you add an image to the list from resources a new image is created and stored in memory.  The address of where the image is stored is essentially what is stored in the list.  So adding the same resource image to the list twice will create two different copies of the image in memory and the list will contain two different addresses for the 'same' image.  The images may be identical but they are not the same image because they exist in two different memory locations.

    When you compare the images later the comparison will just check the memory addresses of the images to determine if they are the same image and so the test will always fail.

    So I have changed the code back to my original plan to assign the same image to two different PictureBoxes.

    I started with a blank form and just added 16 PictureBoxes in a 4x4 layout, leaving the variable names at the defaults.  My image names are different to yours so you will have to modify those.

    Option Strict On
    Option Infer Off
    Public Class Form1
       Private ListOfImages As List(Of Image)
       Private ListOfBoxes As List(Of PictureBox)
       Private Rnd As New Random
       Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
          ListOfImages = CreateImageList()
          ListOfBoxes = CreatePictureBoxList()
          AssignImagesToPictureBoxes()
       End Sub
       Private Function CreateImageList() As List(Of Image)
          Dim ImageList As New List(Of Image) From {My.Resources.Pic1, My.Resources.Pic2, My.Resources.Pic3, _
                                                    My.Resources.Pic4, My.Resources.Pic5, My.Resources.Pic6, _
                                                    My.Resources.Pic7, My.Resources.Pic8}
          Return ImageList
       End Function
       Private Function CreatePictureBoxList() As List(Of PictureBox)
          Dim BoxList As New List(Of PictureBox) From {PictureBox1, PictureBox2, PictureBox3, PictureBox4, PictureBox5, _
                                                       PictureBox6, PictureBox7, PictureBox8, PictureBox9, PictureBox10, _
                                                       PictureBox11, PictureBox12, PictureBox13, PictureBox14, PictureBox15, PictureBox16}
          Return BoxList
       End Function
       Private Sub AssignImagesToPictureBoxes()
          Dim PB As PictureBox
          Dim WhichPictureBoxInList As Integer
          For Each Img As Image In ListOfImages
             WhichPictureBoxInList = Rnd.Next(ListOfBoxes.Count)
             PB = ListOfBoxes(WhichPictureBoxInList)
             PB.Image = Img
             PB.Tag = Img
             ListOfBoxes.Remove(PB)
             WhichPictureBoxInList = Rnd.Next(ListOfBoxes.Count)
             PB = ListOfBoxes(WhichPictureBoxInList)
             PB.Image = Img
             PB.Tag = Img
             ListOfBoxes.Remove(PB)
          Next
       End Sub
       Private Sub PictureBoxClicked(sender As Object, e As 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
          Dim PB As PictureBox = CType(sender, PictureBox)
          PB.Image = CType(PB.Tag, Image)
       End Sub
    End Class
    

    The code is basically what you should have already (with the change discussed above) but I have modified it a bit to make it easier to understand and maintain.  The main difference is that I have split the code into a number of separate methods which are called from the form load event handler.  The reason for doing this is that it breaks the code up into smaller fragments each of which performs a specific purpose.  When coding you should aim to keep any methods (Subs and Functions) to a reasonable size; some suggest that a single screen full is big enough for a method but that isn't always practical.

    You will see another advantage of this when you write the code to restart the game.

    The code as posted assigns each image to both the Image property and the Tag property of the PictureBoxes.  Once you see that the code is working correctly you can comment out the lines which assign to the image property so that they won't be seen on startup.

    Once you've done that check that they appear when you click on a picturebox.

    If all that works then you are ready to code the logic of the game, which you'll find needs very little code.

    Wednesday, March 2, 2016 12:12 PM
  • Ok Thank you so much! But what is the diffeence between dim and private ?  And also for the logic of tha game, is this what i need to do ?

    1. Create the firstclick and secondclick

    2. Compare both, if they have tha same tag, they stay visible, if they don't have the same tag, they become hidden (with .visible = false?)

    3. See if the user has won the game. Should I check if the list of boxes is empty ? Because they've all been assigned to images in the list of images ? Or if all the pictureboxes have tags?

    Wednesday, March 2, 2016 12:51 PM
  • Also, why isn't it "new" list when declaring the lists, and how do i fill them because i seem to have to have and "as" but i had used an "="
    Wednesday, March 2, 2016 1:02 PM
  • nevermind the last question i just saw you filled it later on...
    Wednesday, March 2, 2016 1:03 PM
  • Essentially there is little difference between Dim and Private.  You can only use Dim (not Private) within a method but you can user either at module level.  If you want the full picture you can read all about it here and here.

    The game logic is very simple - the user clicks on a box and the image is displayed.  They then click on another box and it's image is displayed.  If the images match they remain - if not then after a short delay they disappear and the user tries again.

    The delay before the images are cleared will be determined by a timer so add a timer to your form and set its interval to about 1/2 second (you set it in milliseconds)

    In order to clear non matching images you need to remember which two boxes the user clicked so declare two variables at the top of your code (i.e. with module scope) of type PictureBox which will be used to store the boxes you click on.

    In order to keep track of where you are in the game you need to know whether or not the user is clicking on the first box or the second box.  That can be put another way - either the user is clicking on the first box or he isn't.  Which is clearly a binary choice and so you can use a Boolean variable to store this which should also be declared at the top of the code.

    In the PictureBox click handler add code to do the following:

    • Display the image in the box clicked on.
    • Set the boolean variable to indicate if this is the first or second box.
    • Depending upon whether this is the first or second box assign the clicked box to one of the two variables which store which boxes you have clicked on.
    • If this is the first box then no more to be done.
    • If this is the second box then compare the images, referencing the images through the two variables mentioned above.
    • If the images match then no more to be done.
    • If the images don't match then start a timer which will clear them both after a short delay

    Then in the timer's tick event handler you need to add code to:

    • Stop the timer.
    • Clear the two PictureBox images by setting the Image property to Nothing.

    And that is it - with less than 20 lines of code you have a working game.

    Obviously it needs some additions but they are easy once you have the bare bones of it working.

    Determining when the game is complete can be as simple as keeping a count of how many boxes are displaying images and telling the user when they are all done.

    Restarting the game is easy just clear the counter and create and fill a new list of boxes and assign the images to them.

    You will also need to handle the situation where the user clicks on the same box twice.

    And what happens if the user is quick and clicks on another box while the timer is still running.  Any issues there need to be handled as well.

    Going back to earlier questions:

    Breakpoints and stepping through the code are basic debugging techniques which you must learn if you are to successfully write code.  I'm amazed your teacher hasn't covered this.

    To set a breakpoint you can click on the grey bar to the left of the code opposite the line where you want the breakpoint.  This will create a brown(ish) circle on the bar and highlight the line.  Then when you run the code it will stop running when it gets to that line and you can investigate the state of your variables.

    Once the program has stopped at a breakpoint you can then single step through the following code by pressing F8 (or F10 or F11 - Microsoft in their wisdom seem to keep changing it).

    Both of these are on the Debug menu and so you can see the keyboard shortcuts on there against Debug | StepInto and Debug | Toggle Breakpoint.




    • Edited by Dave299 Wednesday, March 2, 2016 1:25 PM
    • Marked as answer by Peanut123 Thursday, March 3, 2016 12:29 AM
    Wednesday, March 2, 2016 1:12 PM
  • And how will i do if the picture box has already been clicked ?
    Wednesday, March 2, 2016 1:22 PM
  • Yes it's simpler to not show it but it's not difficult to user a timer to clear the images and I think it makes for a better game but that's a personal choice of course.  Maybe get smart and do it both ways and allow the user to make the choice of how to play.

    Also using a timer enforces a certain delay in the play and so if you later decided to add a timer to time the overall time taken to complete the game it would become more of a memory game rather than just finding out who can click every box on the form as quickly as possible.

    Note that I am not suggesting showing the picture with a timer.  The timer is used to hide the pictures if they don't match.

    Wednesday, March 2, 2016 1:30 PM
  • And how will i do if the picture box has already been clicked ?

    Don't worry about that for now.  Get the code for the rest of it working and it should then be clear what you need to do to detect two clicks on the same box.

    Wednesday, March 2, 2016 1:37 PM
  • Ok so I went back to an example you had given me two weeks ago so this would be the code ? I just don't understand the refresh part . Also you had written Timer.Start()... Is is any different of what I wrote ?

    • Edited by Peanut123 Thursday, March 3, 2016 2:47 PM
    Wednesday, March 2, 2016 1:57 PM
  • Also you had declared your timer at the very beginning... Should I do that ?
    Wednesday, March 2, 2016 1:59 PM
  • And don't i eventually have to say that firstclickedbox and secondclicked box = Nothing so that the user can click on two new boxes ? And I don't quite understand how to do if the same box is clicked twice...
    Wednesday, March 2, 2016 2:05 PM
  • Ok so I went back to an example you had given me two weeks ago so this would be the code ? I just don't understand the refresh part

    You'll learn more if you don't just copy that code.  Go through the bullet points above and code it yourself.  The refresh was just a belt and braces to ensure that the displayed image on the picturebox updated.  It shouldn't be necessary.

    Also you had written Timer.Start()... Is is any different of what I wrote ?

    There is essentially no difference between Timer.Start and Timer.Enabled.  Start is simply a method which sets the Enabled property.  Similarly with Timer.Stop

    Public Sub [Start]()
        Me.Enabled = True
    End Sub


    Public Sub [Stop]()
        Me.Enabled = False
    End Sub


    Also you had declared your timer at the very beginning... Should I do that ?

    Follow what I've said above and you will realise that question is unnecessary.

    And don't i eventually have to say that firstclickedbox and secondclicked box = Nothing so that the user can click on two new boxes

    Maybe - when you code it up you can follow through the logic and work it out for yourself.

    I don't quite understand how to do if the same box is clicked twice

    As already stated once you have it coded that will become obvious.



    • Edited by Dave299 Wednesday, March 2, 2016 2:37 PM
    Wednesday, March 2, 2016 2:35 PM
  • Ok thank you I will try writing it myself.
    Wednesday, March 2, 2016 2:41 PM
  • But for detecting wether the person won or not, is what i wrote ok ? Because I understand that the picture are assigned as soon as the form loads so obviously the message will appear at the very begining. So how do i count the picture boxes that are displaying an image ?
    Wednesday, March 2, 2016 2:44 PM
  • But for detecting wether the person won or not, is what i wrote ok ? Because I understand that the picture are assigned as soon as the form loads so obviously the message will appear at the very begining. So how do i count the picture boxes that are displaying an image ?

    Well it's obviously not ok is it?

    What I said earlier was "Determining when the game is complete can be as simple as keeping a count of how many boxes are displaying images and telling the user when they are all done."

    So declare a variable to store that count and update it as you go.  When you get to 16 it's game over.

    Wednesday, March 2, 2016 2:55 PM
  • Oh now I get it because you seperated it with titles now I just have to write this to restart the game right after having said the user won ?

    CreateImageList()

    CreatePictureBoxList()

    AssignImagesToPictureBoxes()

    Wednesday, March 2, 2016 6:50 PM
  • Ok I think I figured out how to do if the user clicks on the same box twice !
            If FirstClick Then
                FirstClickedBox = PB
                'ListOfBoxesDisplayingImages.Add(FirstClickedBox)
            Else
                SecondClickedBox = PB
                'ListOfBoxesDisplayingImages.Add(SecondClickedBox)
                If FirstClickedBox IsNot SecondClickedBox Then
                    If FirstClickedBox.Image IsNot SecondClickedBox.Image Then
                        Timer1.Enabled = True
                    End If
                Else
                    MsgBox("You clicked the same image twice")
                    Timer1.Enabled = False
                    FirstClickedBox.Image = Nothing
                    SecondClickedBox.Image = Nothing
                End If
            End If

    Wednesday, March 2, 2016 7:02 PM
  • Keep talking - you're getting there.

    I had envisaged you just using an integer variable to count the number of boxes matched but here's another idea.  When you actually start the game the list of pictureboxes is empty and it is not used during the game - it's only used during the initial assignment of pictures to each picturebox.

    So what you could do is add the pictureboxes back in to the existing list as the player matches them.  Then all you need to check is the length of the list after each match to determine if the game is complete.

    That also means that you don't have to recreate the list to restart - just assign a different pattern of images and clear all the image properties, which you would do using a loop in a separate method.


    • Edited by Dave299 Wednesday, March 2, 2016 7:05 PM
    Wednesday, March 2, 2016 7:04 PM
  • Is the list of pictureboxes empty because they've all been taken out when we assigned them to images ?
    Wednesday, March 2, 2016 7:11 PM
  • Also when you say when the player matches them would i have to create an ELSE after the IF 1rstClickedBox.Image Is Not 2ndClickedBox.Image ?
    Wednesday, March 2, 2016 7:13 PM
  • Ok this is probably more complicated that in could be but is this ok because it checks for a winner after the whole firstclick thing. Should I put it earlier ? Or seperate it into a different sub?
      Dim NumberOfBoxesDisplayingImages As Integer NumberOfBoxesDisplayingImages = ListOfBoxes.Count If NumberOfBoxesDisplayingImages = 16 Then MsgBox("You won !") Timer1.Enabled = False For Each PBox As PictureBox In ListOfBoxes PBox.Image = Nothing Next CreatePictureBoxList() AssignImagesToPictureBoxes() End If 
    

      Dim NumberOfBoxesDisplayingImages As Integer NumberOfBoxesDisplayingImages = ListOfBoxes.Count 
    If NumberOfBoxesDisplayingImages = 16 Then 
    MsgBox("You won !") 
    Timer1.Enabled = False 
    For Each PBox As PictureBox In ListOfBoxes 
    PBox.Image = Nothing 
    Next 
    


    • Edited by Peanut123 Thursday, March 3, 2016 3:38 AM
    Wednesday, March 2, 2016 7:23 PM
  • And what did you mean by : And what happens if the user is quick and clicks on another box while the timer is still running.  Any issues there need to be handled as well. Do you mean if he clicks on 3 pictureboxes before the computer recognizes the firstclickedbox and secondclickedbox ? If so, how would I fix that ?
    Wednesday, March 2, 2016 7:28 PM
  • And also should i program Something for if the user clicks on a picturebox that has already been assigned an image ?
    Wednesday, March 2, 2016 7:32 PM
  • That's looking promising but I see a few issues:

    I don't see anywhere in there where you are setting FirstClick and without that the code won't work correctly.

    What I did was to use:

    FirstClick = Not FirstClick

    at the start of the click handler.

    That probably looks a bit strange so give it some thought and think about why it works.

    There is no need to clear the SecondBox.Image if the user clicks on the same box as obviously SecondBox will be the same as FirstBox in that situation.  There's also no need to stop the timer as it won't be running at that point.

    You also appear to be missing the code needed to display the images.

    Don't forget the other thing that could go wrong is if the user clicks on a box while the timer is running.  That would upset all the logic of the code so you need to prevent it happening.


    • Edited by Dave299 Wednesday, March 2, 2016 7:37 PM
    Wednesday, March 2, 2016 7:35 PM
  • Also (I'm sorry I have so much questions...), I would eventually like to put a button that says start and then when the game is done, it's name would change to restart. I would probably desactivate the button (I don't know how) when the game is playing. If I do that, what parts of my code should I put in the button click sub ? I guess all the pictureboxClicked sub would go into it ? If so, how ?
    Wednesday, March 2, 2016 7:36 PM
  • I'm not sure I understand this part, Don't forget the other thing that could go wrong is if the user clicks on a box while the timer is running.  That would upset all the logic of the code so you need to prevent it happening. You mean if the user clicks on a 3rd box while the computer is processing ?
    Wednesday, March 2, 2016 7:42 PM
  • As currently written there is no need for a start button.  If you want to prevent the user from starting without clicking on a start button then one way would be to disable the picturebox click handler until the button is clicked.  That way nothing will happen if they click on the pictureboxes until they have clicked the start button.

    You could do that by removing the handles clause from the picturebox click handler and add the following code to your button click event handler:

          For Each PB As PictureBox In ListOfBoxes
             AddHandler PB.Click, AddressOf PictureBoxClicked
          Next

    Also in the button click event handler you can change the button text and disable the button so it can't be clicked twice.  Enable it again when the game is won.

    An issue which will arise here is that each time you click the button you will add another handler so clicking a box during the second game will run the code twice, which is not desirable.

    However there is another issue with the current code which arises if the user clicks on a box which has already been matched.  You can kill two birds with one stone by removing the handler for both pictureboxes once a match has been found.  Do that with RemoveHandler in a similar way to how the handlers are added above.  That will prevent a box being clicked again once it has been matched and also prevent double handlers being added when you restart (provided you only allow a restart after completion)

    It sounds more complicated than it actually is - give it a try.

    I'm going to get dinner so won't be responding for a while.
    • Edited by Dave299 Wednesday, March 2, 2016 8:00 PM
    Wednesday, March 2, 2016 7:58 PM
  • Ok it seems to work when i click on a picturebox that already has an image, the computer pretty much ignores it and the user can pick another 1rst or 2nd image.
                    Else
                        ListOfBoxes.Add(FirstClickedBox)
                        ListOfBoxes.Add(SecondClickedBox)
                        RemoveHandler FirstClickedBox.Click, AddressOf PictureBoxClicked
                        RemoveHandler SecondClickedBox.Click, AddressOf PictureBoxClicked
                    End If

    Wednesday, March 2, 2016 8:25 PM
  • Also the pictures show up even before i click on the button. I just added another timer, and now it doen't recognize  pairs anymore...

    Public Class Form1

    Private ListOfImages As List(Of Image)

    Private ListOfBoxes As List(Of PictureBox)

    Private Random As New Random

    Private FirstClickedBox As PictureBox

    Private SecondClickedBox As PictureBox

    Private FirstClick As Boolean

    Private Compteur As Integer

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

    Label1.Text = CStr(Compteur)

    Compteur = 1000

    ListOfImages = CreateImageList()

    ListOfBoxes = CreatePictureBoxList()

    AssignImagesToBoxes() End Sub Private Function CreateImageList() As List(Of Image) Dim ListOfImages As New List(Of Image) From {My.Resources.Pic1, My.Resources.Pic2, My.Resources.Pic3, _ My.Resources.Pic4, My.Resources.Pic5, My.Resources.Pic6, _ My.Resources.Pic7, My.Resources.Pic8} Return ListOfImages End Function Private Function CreatePictureBoxList() As List(Of PictureBox) Dim ListOfBoxes As New List(Of PictureBox) From {PictureBox1, PictureBox2, PictureBox3, PictureBox4, PictureBox5, _ PictureBox6, PictureBox7, PictureBox8, PictureBox9, PictureBox10, _ PictureBox11, PictureBox12, PictureBox13, PictureBox14, PictureBox15, PictureBox16} Return ListOfBoxes End Function Private Sub AssignImagesToPictureBoxes() Dim PB As PictureBox Dim WhichPictureBoxInList As Integer For Each Img As Image In ListOfImages WhichPictureBoxInList = Random.Next(ListOfBoxes.Count) PB = ListOfBoxes(WhichPictureBoxInList) PB.Tag = Img ListOfBoxes.Remove(PB) WhichPictureBoxInList = Random.Next(ListOfBoxes.Count) PB = ListOfBoxes(WhichPictureBoxInList) PB.Tag = Img ListOfBoxes.Remove(PB) Next End Sub Private Sub PictureBoxClicked(ByVal sender As Object, ByVal e As EventArgs) Dim PB As PictureBox = CType(sender, PictureBox) FirstClick = Not FirstClick PB.Image = CType(PB.Tag, Image) If FirstClick Then FirstClickedBox = PB Else SecondClickedBox = PB If FirstClickedBox IsNot SecondClickedBox Then If FirstClickedBox.Image IsNot SecondClickedBox.Image Then Timer1.Enabled = True Else ListOfBoxes.Add(FirstClickedBox) ListOfBoxes.Add(SecondClickedBox) RemoveHandler FirstClickedBox.Click, AddressOf PictureBoxClicked RemoveHandler SecondClickedBox.Click, AddressOf PictureBoxClicked End If Else MsgBox("You clicked the same box twice") FirstClickedBox.Image = Nothing

    SecondClickedBox.Image = Nothing End If End If End If End Sub Dim HowMany as Integer

    HowMany = ListOfBoxes.Count If HowMany = 16 Then Timer1.Enabled = False MsgBox("You won !") For Each PBox As PictureBox In ListOfBoxes PBox.Image = Nothing Next Button1.Enabled = True Label1.Text = 1000 End If End Sub Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Compteur = 1000 Label1.Text = Compteur Button1.Enabled = False Timer1.Enabled = True End Sub Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick If compteur > 0 Then compteur = compteur - 1 LabelCompteur.Text = compteur Else

    Timer1.Enabled = False ButtonDemarrer.Text = "Demarrer" compteur = 100 End If End Class



    .
    • Edited by Peanut123 Thursday, March 3, 2016 2:56 PM
    Wednesday, March 2, 2016 9:45 PM
  • It was getting so close - and now you've broken it :-(

    The biggest issue was that you were trying to make the timer do two things which was never going to work.

    If you wanted to add a countdown timer to the app then you should have added another timer, not tried to use the existing one.

    Anyway to save time I've done that for you and fixed the other things you had broken - the following seems to work ok:

    Option Strict On
    Option Infer Off
    Public Class Form1
       Private ListOfImages As List(Of Image)
       Private ListOfBoxes As List(Of PictureBox)
       Private Random As New Random
       Private FirstClickedBox As PictureBox
       Private SecondClickedBox As PictureBox
       Private FirstClick As Boolean
       Private Compteur As Integer
       Private TimeAllowed As Integer = 100
       Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
          Label1.Text = CStr(Compteur)
          ListOfImages = CreateImageList()
          ListOfBoxes = CreatePictureBoxList()
       End Sub
       Private Function CreateImageList() As List(Of Image)
          Dim ListOfImages As New List(Of Image) From {My.Resources.Pic1, My.Resources.Pic2, My.Resources.Pic3, _
                                                    My.Resources.Pic4, My.Resources.Pic5, My.Resources.Pic6, _
                                                    My.Resources.Pic7, My.Resources.Pic8}
          Return ListOfImages
       End Function
       Private Function CreatePictureBoxList() As List(Of PictureBox)
          Dim ListOfBoxes As New List(Of PictureBox) From {PictureBox1, PictureBox2, PictureBox3, PictureBox4, PictureBox5, _
                                                       PictureBox6, PictureBox7, PictureBox8, PictureBox9, PictureBox10, _
                                                       PictureBox11, PictureBox12, PictureBox13, PictureBox14, PictureBox15, PictureBox16}
          Return ListOfBoxes
       End Function
       Private Sub AssignImagesToPictureBoxes()
          Dim PB As PictureBox
          Dim WhichPictureBoxInList As Integer
          For Each Img As Image In ListOfImages
             WhichPictureBoxInList = Random.Next(ListOfBoxes.Count)
             PB = ListOfBoxes(WhichPictureBoxInList)
             PB.Tag = Img
             ListOfBoxes.Remove(PB)
             WhichPictureBoxInList = Random.Next(ListOfBoxes.Count)
             PB = ListOfBoxes(WhichPictureBoxInList)
             PB.Tag = Img
             ListOfBoxes.Remove(PB)
          Next
       End Sub
       Private Sub PictureBoxClicked(ByVal sender As Object, ByVal e As EventArgs)
          If Not Timer1.Enabled Then
             Dim PB As PictureBox = CType(sender, PictureBox)
             FirstClick = Not FirstClick
             PB.Image = CType(PB.Tag, Image)
             If FirstClick Then
                FirstClickedBox = PB
             Else
                SecondClickedBox = PB
                If FirstClickedBox IsNot SecondClickedBox Then
                   If FirstClickedBox.Image IsNot SecondClickedBox.Image Then
                      Timer1.Start()
                   Else
                      ListOfBoxes.Add(FirstClickedBox)
                      ListOfBoxes.Add(SecondClickedBox)
                      RemoveHandler FirstClickedBox.Click, AddressOf PictureBoxClicked
                      RemoveHandler SecondClickedBox.Click, AddressOf PictureBoxClicked
                      CheckForWinner()
                   End If
                Else
                   MsgBox("You clicked the same box twice")
                   FirstClickedBox.Image = Nothing
                End If
             End If
          End If
       End Sub
       Private Sub CheckForWinner()
          If ListOfBoxes.Count = 16 Then
             Timer2.Stop()
             MsgBox("You won in " & (100 - Compteur).ToString & " seconds")
             For Each PBox As PictureBox In ListOfBoxes
                PBox.Image = Nothing
             Next
             Button1.Enabled = True
             Label1.Text = TimeAllowed.ToString
          End If
       End Sub
       Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
          Compteur = TimeAllowed
          Label1.Text = Compteur.ToString
          For Each PB As PictureBox In ListOfBoxes
             AddHandler PB.Click, AddressOf PictureBoxClicked
          Next
          AssignImagesToPictureBoxes()
          Button1.Enabled = False
          Timer2.Start()
       End Sub
       Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
          Timer1.Stop()
          FirstClickedBox.Image = Nothing
          SecondClickedBox.Image = Nothing
       End Sub
       Private Sub Timer2_Tick(sender As Object, e As System.EventArgs) Handles Timer2.Tick
          Compteur -= 1
          Label1.Text = Compteur.ToString
          If Compteur = 0 Then
             Timer2.Stop()
             MsgBox("Your time is up...")
             ResetPictureBoxes()
             Button1.Enabled = True
             Button1.Text = "Redemarrer"
          End If
       End Sub
       Private Sub ResetPictureBoxes()
          ListOfBoxes = CreatePictureBoxList()
          For Each PB As PictureBox In ListOfBoxes
             RemoveHandler PB.Click, AddressOf PictureBoxClicked
             PB.Image = Nothing
             PB.Tag = Nothing
          Next
       End Sub
    End Class
    

    • Edited by Dave299 Wednesday, March 2, 2016 11:01 PM modified code
    Wednesday, March 2, 2016 10:31 PM
  • Thank you so much ! So now, do i have to worry about if the user clicks on a box while the timer is running?
    Wednesday, March 2, 2016 10:36 PM
  • Yes - but I've spotted a few other issues as well after further testing.  I'll post back with the fixes in a little while.
    Wednesday, March 2, 2016 10:47 PM
  • Ok Thank you very much.
    • Marked as answer by Peanut123 Wednesday, March 2, 2016 11:14 PM
    • Unmarked as answer by Peanut123 Wednesday, March 2, 2016 11:14 PM
    Wednesday, March 2, 2016 10:50 PM
  • There was an issue when the additional timer timed out -  if the game was partially completed then the list of pictureboxes and the boxes themselves would be in an undefined state so I've put in a reset method which is called after a timeout to try and ensure a clean start.

    I've modified the code in the post above rather than post it all again.

    I'll leave it up to you to try and find additional problems.

    BTW - best time so far 42 seconds.

    Wednesday, March 2, 2016 11:05 PM
  • I don't quite understand Timer1. Especially the first line in the pictureboxclickedsub. That means if the timer's off? So should i create an ELSE and then tend to the possible issues if the user is very quick and clicks on an image when the timer1's running?
    Wednesday, March 2, 2016 11:20 PM
  • I think I might have found one. I'll try to fix it but the button's name never changes to "Redémarrer" at the second try.
    Wednesday, March 2, 2016 11:30 PM
  • I forgot to mention that I'd fixed that as well.

    That line just ensures that the code in the click handler only runs if the timer isn't running.  If the timer is running the click is ignored.  You don't need to add anything else.

    There may well be other problems - I haven't tested this as well as I would test one of my own applications.  No prizes for finding them though.

    Wednesday, March 2, 2016 11:31 PM
  • Ok I totally understand thank you!
    Thursday, March 3, 2016 12:28 AM
  • One last question if you don't mind, I"m also planning on counting points, say the user gets one point if he matches all the pairs. I think i have to create a new label and create an integer. Then, I just have to add 1 to that integer every time the game is won? And i set it to 0 at the very beginning of the game?

    Many thanks for all your help.

    Thursday, March 3, 2016 12:34 AM