AlphaOne AlphaOne - 12 days ago 8
Vb.net Question

Using control array for shuffling picture boxes

So I want to create a concentration-style memory matching game. But for now I want to just focus on filling picture boxes. I want the pictures to be shuffled in a random order each time the game is loaded. My teacher recommended using a control array and sent me this link http://www.acthompson.net/DotNet/ControlArrays.htm

I'm still quite confused as there's red lines everywhere and I don't know how to add the images to the program. Initially I wanted to add the pictureboxes whilst building but this tutorial suggests doing it at runtime.

There's red lines under InitializeComponent()and the card()'s. Why? And how do I add images that I have saved in a file?

Also I'd like to know if I need the double Class declaration? The name of the class is 'Form' and 'Form1' is referring to the form itself. When I just declare 'Form1' it says 'class Form1 and partial class Form1 clash.' Can I just declare 'Form' and it will be able to interact with the form?

tldr; how to fill a control array with picture boxes which can be shuffled each time the game is run?

Thank you in advance. My code so far:

Public Class Form

Public Class Form1

Inherits System.Windows.Forms.Form

Dim cards(23) As PictureBox


Public Class Form
Public Class Form1

Inherits System.Windows.Forms.Form

Dim cards(23) As PictureBox

Sub New()
InitializeComponent()
cards = New PictureBox() {PictureBox1, PictureBox2, PictureBox3, PictureBox4, PictureBox5, PictureBox6, PictureBox7, PictureBox8, PictureBox9, PictureBox10, PictureBox11, PictureBox12, PictureBox13, PictureBox14, PictureBox15, PictureBox16, PictureBox17, PictureBox18, PictureBox19, PictureBox20, PictureBox21, PictureBox22, PictureBox23, PictureBox24}
End Sub

End Class


End Class

I've tried this and various other configurations but ti still isn't working. Where have I made a mistake?

UPDATE:

So I've played around with this and I've had a couple of issues.
1. It says that Path is not declared so I did IO.Path and that seems to be okay. I don't know if it's suitable though
2. It says that PictureBox1,etc, are not declared and inaccessible. The same for Img Folder. I suppose the path to the folder with my images is incorrect

Public Class Form1

'picture boxes

Private pBoxes As PictureBox()

'images

Private imgs As String()

'random number generator

Private rNum As Random

'cover image

Private coverImg As String = "bg.jpeg"

'timer

Private dt As DateTime

'turns cards

Private pbFirst As PictureBox

Private pbSecond As PictureBox

Private matches As Int32 = 0



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

Dim ImgFolder As String

rNum = New Random()

pBoxes = New PictureBox() {PictureBox1, PictureBox2, PictureBox3, PictureBox4, PictureBox5, PictureBox6, PictureBox7, PictureBox8, PictureBox9, PictureBox10, PictureBox11, PictureBox12, PictureBox13, PictureBox14, PictureBox15, PictureBox16, PictureBox17, PictureBox18, PictureBox19, PictureBox20, PictureBox21, PictureBox22, PictureBox23, PictureBox24}

'where images are stored

ImgFolder = IO.Path.Combine(Environment.GetFolderPath("H:\Test images"))

coverImg = IO.Path.Combine(ImgFolder, coverImg)


For Each p As PictureBox In pBoxes

p.ImageLocation = coverImg

Next

'NewGame()

End Sub

'Private Sub NewGame()

' reset everything that matters

'matches = 0

'pbFirst = Nothing

'pbSecond = Nothing

' repick, reshuffle

'PickImages()

'Shuffle()

'dt = DateTime.Now

'tmrMain.Enabled = True

'End Sub


End Class

Yet another update:

I did have pictureboxes on my first version but not in this one. Can't believe I made such a silly mistake... It's fixed that but it is still saying my ImgFolder is undeclared and inaccessible. Btw, thank you so much for your patience and help so far.

Imports System.IO

Public Class Form1

'array of picture boxes
Private pBoxes As PictureBox()
'array of images
Private imgs As String()
'random number generator
Private rNum As Random
'cover image
Private coverImg As String = "bg.jpeg"

'timer
Private dt As DateTime

'turns cards
Private pbFirst As PictureBox
Private pbSecond As PictureBox
Private matches As Int32 = 0


Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
rNum = New Random()

pBoxes = New PictureBox() {PictureBox1, PictureBox2, PictureBox3, PictureBox4,
PictureBox5, PictureBox6, PictureBox7, PictureBox8,
PictureBox9, PictureBox10, PictureBox11, PictureBox12, PictureBox13, PictureBox14, PictureBox15, PictureBox16, PictureBox17, PictureBox18, PictureBox19, PictureBox20, PictureBox21, PictureBox22, PictureBox23, PictureBox24}

' where you keep YOUR images

ImgFolder = "F:\COMPUTER SCIENCE\Test images"

coverImg = Path.Combine(ImgFolder, coverImg)
For Each p As PictureBox In pBoxes
p.ImageLocation = coverImg
Next

'NewGame()
End Sub

'Private Sub NewGame()
' reset everything that matters
'matches = 0
'pbFirst = Nothing
'pbSecond = Nothing
' repick, reshuffle
'PickImages()
'Shuffle()

'dt = DateTime.Now
'tmrMain.Enabled = True
'End Sub


End Class

Answer

You probably do not want to load the match images into the PictureBoxes at startup - they should start with the same image until they are picked, no? You will also want to avoid actually using images at all - if you create/load images, you are also responsible for disposing of them. Use the ImageLoacationproperty to specify the path to a file.

This game version uses images from a deck of cards. This is just the start up since this appears to be homework.

Public Class frmGame
    Private pbs As PictureBox()
    Private myImgs As String()        ' img file paths
    Private RNG As Random

    Private ImgFolder As String
    Private CoverImg As String = "b1fv.png"
    ' crude timer
    Private dt As DateTime    

    ' turn elements - first and second pbs clicked,
    ' matches so you know when it is Game Over
    Private pbFirst As PictureBox
    Private pbSecond As PictureBox
    Private matches As Int32 = 0

    Private Sub frmGame_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        RNG = New Random()

        pbs = New PictureBox() {PictureBox1, PictureBox2, PictureBox3, PictureBox4,
                               PictureBox5, PictureBox6, PictureBox7, PictureBox8,
                               PictureBox9, PictureBox10, PictureBox11, PictureBox12}

        ' where you keep YOUR images
        ImgFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),
                                 "DevGraphics", "Cards")

        CoverImg = Path.Combine(ImgFolder, CoverImg)
        For Each p As PictureBox In pbs
            p.ImageLocation = CoverImg
        Next

        NewGame()
    End Sub

    Private Sub NewGame()
        ' reset verything that matters
        matches = 0
        pbFirst = Nothing
        pbSecond = Nothing
        ' repick, reshuffle
        PickImages()
        Shuffle()

        dt = DateTime.Now
        tmrMain.Enabled = True
    End Sub
End Class
  • The cards are from www.jfitz.com/cards/ which apparently no longer exists
  • In the click event, the code can store the first and second PB clicked using pbFirst and pbSecond
  • PickImages would load the file names to the array
    • start with an array of values 1-52
    • shuffle them (your shuffle on your previous question is wrong - there are many Shuffle answers like this one on SO)
    • take half as many as you need (12 for a 24 match game), duplicate them
  • Shuffle that array
    • map them by showing myImgs(n) in a PictureBox where n is the index of the clicked picturebox in the array above
    • the fitz cards have a numerical set where 1.png is the Ace-Spades, 2 maps to the 2-spades etc so converting an integer to a card image file name is simple.
  • CoverImg is the generic you-havent-found-a-match image. You could leave them blank

Using ImageLocation rather than an image also allows you to easily compare if pbFirst has the same image as pbSecond

Add timers for game and delays, and eventually a 12 card version might look like:

enter image description here

You appear to have a form declaration within a form. I'd start over with a new form.

Comments