skip to Main Content

I have created a form in visual studio C# and am trying to assign a unique random category to each label (numbered from 1 to 9), but it seems that there are repeat values every time that I click the randomize button. I took the code from the Fisher-Yates shuffle, which should work as intended, what part am I missing that gives my labels non-unique values? See code below:

   public void button2_Click(object sender, EventArgs e)

    {

        List<String> unshuffledCategories = new List<String> { "History", "Geography", "Music",    "Animals", "Logos", "Flags", "Food", "games", "Sports" };
        List<String> shuffledCategories = new List<string>();

        Random r = new Random();

        var labels = new List<Label> { lblField1, lblField2, lblField3, lblField4, lblField5, lblField6, lblField7, lblField8, lblField9 };

        for (int n = unshuffledCategories.Count; n > 0; --n)
        {
            int k = r.Next(n);

            String temp = unshuffledCategories[k];
            shuffledCategories.Add(temp);
        }

        for (int i = 0; i < labels.Count; i++)
        {
            labels[i].Text = shuffledCategories[i];
        }
    }

Hope someone can help me out, much appreciated <3!

I tried to create a form which pulls unique random elements from a string list I have created in C#, I was expecting it to provide random unique values, but values are nearly always repeated when I click the button to execute the code.

2

Answers


  1. your problem is in this for loop. In each iteration of the loop you are getting a random number between 1 and (9-n). there is nothing preventing you from getting the same number on a subsequent iteration. In theory you could end up getting "1" all 9 times.

        for (int n = unshuffledCategories.Count; n > 0; --n)
        {
            int k = r.Next(n);
    
            String temp = unshuffledCategories[k];
            shuffledCategories.Add(temp);
        }
    

    You could try this instead:

        for (int n = labels.Count; n > 0; --n)
        {
            int k = r.Next(unshuffledCategories.Count);
    
            String temp = unshuffledCategories[k];
            unshuffledCatogories.Remove(temp);
            shuffledCategories.Add(temp);
        }
    

    This way you are removing the item from unshuffledCategories each time and getting a random value between 0 and the remaining elements so you wont end up with duplicates.

    Login or Signup to reply.
  2. So, you want to shuffle a list, let’s extract it as a method:

    private static void Shuffle<T>(IList<T> list) {
      for (int i = 0; i < list.Count - 1; ++i) {
        int j = Random.Shared.Next(i, list.Count);
    
        (list[i], list[j]) = (list[j], list[i]);
      }
    }
    

    Then we can put the rest as easy as

    var categories = new List<String> { 
      "History", "Geography", "Music", "Animals", "Logos", "Flags", "Food", "games", "Sports" 
    };
    
    Shuffle(categories);
    
    var labels = new List<Label> { 
      lblField1, lblField2, lblField3, lblField4, lblField5, lblField6, lblField7, lblField8, lblField9 
    };
    
    for (int i = 0; i < labels.Count; i++) 
      labels[i].Text = categories[i];
    

    Another approach is to use Linq:

    using System.Linq;
    
    ...
    
    var categories = new List<String> { 
      "History", "Geography", "Music", "Animals", "Logos", "Flags", "Food", "games", "Sports" 
    };
    
    var labels = new List<Label> { 
      lblField1, lblField2, lblField3, lblField4, lblField5, lblField6, lblField7, lblField8, lblField9 
    };
    
    var pairs = categories
      .OrderBy(_ => Random.Shared.NextDouble()) // Shuffle
      .Zip(labels, (cat, lbl) => (cat, lbl));
    
    foreach (var (cat, lbl) in pairs)
      lbl.Text = cat;
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search