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:
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.