Home > OS >  Optimizing randomization in C# Windows Form Application
Optimizing randomization in C# Windows Form Application

Time:05-10

I am making an UNO game for a C# course using the Windows Form template in Visual Studio. I have run into a little problem while randomizing the user's starting hand. I am using a Random object to randomize the cards, and, when I start the project, they are all the same card. I know that I could probably just make multiple random objects, but I was wondering if this could be optimized somehow. Here is the code-

public void hand()
{
    string dir = "C:/Users/aless/OneDrive - Aquinas College/Coding/Locker/C#/CSNET Tasks/GUI Images/UNO Cards";
    FileInfo[] files = new DirectoryInfo(dir).GetFiles();
    Random rand = new Random();
    int index = rand.Next(files.Length);
    string card_path = dir   "/"   files[index].Name;
    card1.Image = Image.FromFile(card_path);
    card1.SizeMode =
            PictureBoxSizeMode.StretchImage;
    card2.Image = Image.FromFile(card_path);
    card2.SizeMode =
            PictureBoxSizeMode.StretchImage;
    card3.Image = Image.FromFile(card_path);
    card3.SizeMode =
            PictureBoxSizeMode.StretchImage;
    card4.Image = Image.FromFile(card_path);
    card4.SizeMode =
            PictureBoxSizeMode.StretchImage;
    card5.Image = Image.FromFile(card_path);
    card5.SizeMode =
            PictureBoxSizeMode.StretchImage;
    card6.Image = Image.FromFile(card_path);
    card6.SizeMode =
            PictureBoxSizeMode.StretchImage;
    card7.Image = Image.FromFile(card_path);
    card7.SizeMode =
            PictureBoxSizeMode.StretchImage;
}

Edit- there is one error that I am receiving in the code from John: enter image description here

CodePudding user response:

When simulating a card game in code, you should actually do it like you would with real cards, i.e. randomise the entire deck and then take one card at a time from that deck. I would do that something like this:

private Random rng = new Random;
private Queue<int> deck;

private void Form1_Load(...)
{
    deck = new Queue<int>(Enumerable.Range(1, 52).OrderBy(n => rng.NextDouble()));
}

rng is the one and only random number generator and deck is a Queue of the objects that represent the cards. I'm using int in this simple example but you can use whatever is appropriate.

The code first generates the full deck of cards in their default order. You can do that however is appropriate for you app but, in this example, Enumerable.Range(1, 52) creates a list of 52 int values in sequential order.

The OrderBy call is what does the actual shuffling and that won't change regardless of the "card" type you're using. OrderBy(n => rng.NextDouble()) generates a random number for each of your "cards" and then orders the "cards" based on those number.

Finally, a new generic Queue is created and populated with the randomised list of "cards". With the Queue, you simply call Dequeue and it will remove the next item and return it. Because the list was randomised, you're getting the items back in a random order. You could use a Stack and call Pop and it would work the same way, just taking items from the other end of the list. If, for instance, you need a hand of 5 cards, you just call Dequeue or Pop 5 times.

You don't have to do this but, in your case, I'd suggest creating all the Image objects at the start. They can then be your "card" objects or part thereof, e.g. you might have a class with an Image property for display but also a name and maybe a numerical value.

  •  Tags:  
  • c#
  • Related