Hi guys, I'm new here so please help me. I wanted to create a memory game where in the user clicks on two images and matches them. However, in the middle of creating it I encountered a weird problem - whenever I set the "Visible" property of the PictureBox on "true" it doesn't show up but doing the opposite, setting it to "false" it works just fine. Here's the part of putting images in the PictureBox and setting its visibility to "false" and "true" on the "picture_Click" event.

.......
//assigning images in every picturebox in random and at the sametime setting its visibility on false
foreach (Control control in tlpHome.Controls)
            {
                PictureBox picBox = control as PictureBox;
                if (picBox != null)
                {
                    int randomNumber = random.Next(image.Count);
                    picBox.Image = image[randomNumber];
                    picBox.Visible = false;
                    image.RemoveAt(randomNumber);
                }
            }

//the event handler 'Click' of PictureBox. Should set the visibility of PictureBox on 'true' whenever it's clicked.
private void picture_Click(object sender, EventArgs e)
        {
            PictureBox clickedPicture = sender as PictureBox;

            if (clickedPicture != null)
            {
                if (clickedPicture.Visible == true)
                    return;
                
                clickedPicture.Visible = true;
            }
        }

Doesn't have any errors while building it. But it works fine if I reverse it which is the weird part - setting "picBox.Visible = true" and setting "clickedPicture.Visible == false" and clickedPicture.Visible = false"

Please help guys... Thanks!

Dani AI

Generated

Nice progress, — this was not a bug in WinForms. Controls with Visible = false are removed from hit‑testing and will never receive mouse events, so you cannot click them to make them visible. was right to suggest a placeholder, and 's idea of an ID for comparison is solid. A clean pattern is: keep each PictureBox Visible, show a back/placeholder image, store a card ID (or index) in the PictureBox.Tag, and swap the image on click. Track two selected boxes, compare their IDs, and flip them back after a short delay if they do not match.

Example (concise pattern — not a duplicate of earlier code):

// fields
List<Image> faces = /* fill so faces[id] is the card face for that id */;
Image back = Properties.Resources.CardBack;
List<PictureBox> selected = new List<PictureBox>();
bool lockBoard = false;

// setup
int idx = 0;
foreach (PictureBox pb in tlpHome.Controls.OfType<PictureBox>())
{
    pb.Tag = idx;   // id that maps to faces[idx]
    pb.Image = back;
    pb.Click += Card_Click;
    idx++;
}

private async void Card_Click(object sender, EventArgs e)
{
    if (lockBoard) return;
    var pb = (PictureBox)sender;
    if (selected.Contains(pb)) return;

    int id = (int)pb.Tag;
    pb.Image = faces[id];
    selected.Add(pb);

    if (selected.Count == 2)
    {
        if ((int)selected[0].Tag == (int)selected[1].Tag)
        {
            selected[0].Enabled = selected[1].Enabled = false; // matched
        }
        else
        {
            lockBoard = true;
            await Task.Delay(700);
            selected[0].Image = selected[1].Image = back;
            lockBoard = false;
        }
        selected.Clear();
    }
}

Notes: disable clicks while comparing (shown as lockBoard), disable matched boxes instead of immediately removing them (or set Visible = false only once matched), and avoid sharing/disposing the same Image instance across controls without cloning. This keeps the UI responsive and avoids the original invisible-click problem.

Recommended Answers

All 7 Replies

So the issue is that when you click on a non-visible picture box it doesnt become visible?

I would assume you cant click on a picture box you cannot see therefore may have to consider setting the picture to a placeholder picture and store the assigned images in an array so that when the picture is clicked it flicks between the placeholder 'hidden' image and the actual array stored one.

Apologies for double post can't edit last. The following code may do what you require, obviously you will need to adapt it for your images and resources folder etc.

public partial class Form1 : Form
    {
        Image[] Pictures = new Image[] { Properties.Resources.RandomImage1, Properties.Resources.RandomImage2, Properties.Resources.RandomImage3, Properties.Resources.RandomImage4, Properties.Resources.PlaceHolder };
        string[,] Images = new string[4,2];


        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            //Can make this setting happen randomly as you do
            img1.Image = Pictures[0];
            img2.Image = Pictures[1];
            img3.Image = Pictures[2];
            img4.Image= Pictures[3];
            //When you randomly set, set the second part of the array to the number in the Pictures array that holds that images position.
            Images[0, 0] = "img1";
            Images[0, 1] = "0";
            Images[1, 0] = "img2";
            Images[1, 1] = "1";
            Images[2, 0] = "img3";
            Images[2, 1] = "2";
            Images[3, 0] = "img4";
            Images[3, 1] = "3";
        }

        private void ImageClick(object sender, EventArgs e)
        {
            //If picture is not using the placeholder image
            if (((PictureBox)sender).Image != Pictures[4])
            {
                ((PictureBox)sender).Image = Pictures[4];
            }
            else
            {
                //Set back to the previous image using the stored location in the array
                for (int i = 0; i < Images.Length / 2; i++)
                {
                    if (((PictureBox)sender).Name == Images[i, 0])
                    {
                        ((PictureBox)sender).Image = Pictures[Convert.ToInt32(Images[i, 1])];
                    }
                }
            }
        }
    }

Thanks for that one! :) Im gonna try it..

oh and by the way, I was wondering if after this is successfully compiled, is there a way wherein I could match/compare two images that have been clicked if they are matched or not a match? Since I am doing a matching game..

You could simply use the array that I used to switch the image back from the placeholder value and compare if they hold the same value there so:

if (Images[1,1] == Images[3,1])
{
    bool MatchFound = true;
}

Again just using a for loop or something to search for the name of the sender to allow the array match to happen?

Thanks for that one! :) Im gonna try it..

oh and by the way, I was wondering if after this is successfully compiled, is there a way wherein I could match/compare two images that have been clicked if they are matched or not a match? Since I am doing a matching game..

You could make a simple class that holds the bitmap and an ID of some sort, and just check if the IDs are a match.

class myIDed_Bitmap
{
   public Bitmap myBitmap {get; private set;}
   public int myID {get; private set;}
   public myIDed_Bitmap(Bitmap argBitmap, int argID)
   {
       myBitmap = argBitmap;
       myID = argID;
   }
}

//And to implement the comparison

if (myIDed_Bitmap.myID == someOtherIDedBitmap.myID) Then
{
   //Do something, they are the same
}

//And to implement loading the bitmap to a picturebox:

myPicturebox.Image = myIDed_Bitmap.myBitmap;

This will save you the pixel by pixel comparison. But this always leaves the possibility of 2 pictures being 'allowed' that are exactly the same but since they have different IDs your program will think they are different.

Comparing some type of checksum or hash function of the two image files could be a solution if this is a possibility.

It worked! Thanks for the ideas guys! :D

I'm glad it did :)

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.