Andrei Ursu
Andrei Ursu

Reputation: 23

Randomizing images in picture boxes without repeating

I am pretty new in the programming scene and I want to be able to use a button to show random photos in multiple picture boxes. The thing is that I don't want one photo to show in multiple boxes. So every pictureBox should contain different images. I have searched Google for the past few hours but I haven't been able to get any useful information. What I have now, when pressing the button, every pictureBox goes blank. Though here is my code in the button1_Click :

{
        List<string> name = new List<string>();
        name.Add("0.jpg");
        name.Add("1.jpg");
        name.Add("2.jpg");
        name.Add("3.png");
        List<PictureBox> box = new List<PictureBox>();
        box.Add(pictureBox1);
        box.Add(pictureBox2);
        box.Add(pictureBox3);
        box.Add(pictureBox4);
        a = 4;
        ResourceManager rm = MatchGame.Properties.Resources.ResourceManager;
        for (int i = 0; i < box.Count; i++)
        {
            int randomPic = new Random().Next(0, name.Count);
            string randomName = name[randomPic];
            name.Remove(randomName);
            Image img = rm.GetObject(randomName) as Image;
            box[i].Image = img;`

            }
}

Upvotes: 1

Views: 851

Answers (2)

Gian Paolo
Gian Paolo

Reputation: 4249

An easy way would be to simply shuffle in random order your name list

List<string> name = new List<string>();
name.Add("0.jpg");
name.Add("1.jpg");
name.Add("2.jpg");
name.Add("3.png");

List<PictureBox> box = new List<PictureBox>();
box.Add(pictureBox1);
box.Add(pictureBox2);
box.Add(pictureBox3);
box.Add(pictureBox4);

// 2 lines code for shuffle every kind of IEnumerable
Random r = new Random();
name = name.OrderBy(x => r.Next()).ToList();

ResourceManager rm = MatchGame.Properties.Resources.ResourceManager;
for (int i = 0; i < box.Count; i++)
{
// no need to remove elements from name list
    string randomName = name[i];
    Image img = rm.GetObject(randomName) as Image;
    box[i].Image = img;`
}

this will assure that every picture picked once and only once (as long, of course, number of pictureboxes is the same of images stored in resource).

Be sure that every rm.GetObject returns a different image.

As a side note, never create a new Random() within a loop: instantiate a single Random and keep calling .Next on it (see this question). The above code would be wrong in this way:

name = name.OrderBy(x => new Random.Next()).ToList();

Upvotes: 1

Ken
Ken

Reputation: 2808

What you could do is store the picture references in a Dictionary. Associating the picture names with the PictureBox indexes - then all you need to do is check the dictionary values and see if the picturename is in the dictionary. If it is in the dictionary - then just let the while loop do another loop - to pick another image. To Recycle that all you would need to do is clear the dictionary and the process could start over again.

Dictionary<int, string> MyActivePictures = new Dictionary<int, string>();

Use a concurrentDictionary if you are multithreading.

    // Where MyActivePictures < PictureBoxControl , picturename > is the Dictionary

    Dictionary<int, string> MyActivePictures = new Dictionary<int, string>();
  //  i  is your PictureBoxes index as you loop through them
    int i = 0;
    if(box.Count < name.Length){
    do
    {
        int randomPic = new Random().Next(0, name.Count);
        string randomName = name[randomPic];
        if(!MyActivePictures.Values.Contains[randomName])
        {
            name.Remove(randomName);
            Image img = rm.GetObject(randomName) as Image;
            box[i].Image = img;
            MyActivePictures[i]=randomName;

            i++;
        }
        if (i > name.Length) // exits the loop in case there are more
        {
        i = box.Count + 1;
        }

    }while (i < box.Count);

} I should add that if it is not possible for the above code to get a unique picture - for example picture boxes > number of images. Then this code will hang in an endless loop. You will need to factor in for that scenario in the while loop - if(the iterator I of pictureboxes value > total images - exit the loop. so if(i > totalimages) exit loop. I added the additional code to handle this: however You could just simply include that test in the while condition as well - it is easier ( (i names.Length))

Upvotes: 0

Related Questions