Home > OS >  How to randomize/shuffle two arrays in the same way in c#
How to randomize/shuffle two arrays in the same way in c#

Time:11-26

I have two arrays one is a PictureBox array and the other is an Integer array both have the same number of elements. I want both arrays to be shuffled randomly each time but both shuffled the same way.

Here is a code that works if I use two PictureBox arrays or two Integer arrays, however I want it to shuffle one PictureBox array and one Integer array.

This is the code I want to work: (two different arrays)

PictureBox[] cards = new PictureBox[13];
// PictureBox[] numValue = new PictureBox[13];
int[] numbers = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10 };

Random rnd = new Random();

for (int i = 0; i < cards.Length - 1; i  )
{
    int j = rnd.Next(i, cards.Length);

    PictureBox temp = cards[j];
    cards[j] = cards[i];
    cards[i] = temp;

    temp = numbers[j]; //An error occurs here because numbers is not a PictureBox variable
    numbers[j] = numbers[i];
    numbers[i] = temp; 
}

This is the code that works: (for same arrays)

PictureBox[] numValue = new PictureBox[13];
PictureBox[] cards = new PictureBox[13];
// int[] numbers = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10 };

Random rnd = new Random();

for (int i = 0; i < cards.Length - 1; i  )
{
    int j = rnd.Next(i, cards.Length);

    PictureBox temp = cards[j];
    cards[j] = cards[i];
    cards[i] = temp;

    temp = numValue [j]; 
    numValue [j] = numValue [i];
    numValue [i] = temp; 
}

If you know another different code that can help me feel free to share it!

CodePudding user response:

Just create two temporary variables

for (int i = 0; i < cards.Length - 1; i  )
{
    int j = rnd.Next(i, cards.Length);

    PictureBox tempPictureBox = cards[j]; // One for PictureBox
    cards[j] = cards[i];
    cards[i] = tempPictureBox;

    int tempInt = numValue[j]; // Another one for int
    numValue[j] = numValue[i];
    numValue[i] = tempInt; 
}

CodePudding user response:

If you want a shuffler that you can use on any collection, you can create such a class.

public class Shuffler
{
    private List<Guid> order;
    private List<Guid> createOrder(int count)
    {
        return Enumerable.Range(0, count)
            .Select(i => Guid.NewGuid())
            .ToList();
    }
    
    public Shuffler(int count)
    {
        order = createOrder(count);
    }
    
    public void Reshuffle()
    {
        order = createOrder(order.Count);
    }
    
    public IEnumerable<T> Shuffle<T>(IEnumerable<T> collection)
    {
        return collection.Zip(order)
            .OrderBy(e => e.Second)
            .Select(e => e.First);
    }
}

When you create an instance of Shuffler, it creates internally a list or pseudo random elements (here they are Guids, but it could be randomly chosen integers, or anything you'd like). To shuffle a collection, just pass it to the Shuffle method. Each passed collection will be reordoned in the same exact way.

It could be improved, for instance it expects that each collection will have the same number of elements, and that this number was passed to the Shuffler constructor, this could be relaxed. There is also no error checking, but it should give an idea of the principle.

Here is a usage example. You can try it in Linqpad.

void Main()
{
    // The test collections of different types.
    var cards = Enumerable.Range(0, 13)
        .Select(i => new PictureBox { Foo = $"{i}"})
        .ToArray();
    var numbers = Enumerable.Range(0, 13)
        .ToArray();
    
    // Creation of the Shuffler instance
    var shuffler = new Shuffler(cards.Length);
    
    // Using the Shuffler instance to shuffle collections.
    // Any number of collections can be shuffled that way, in the same exact way.
    cards = shuffler.Shuffle(cards).ToArray();
    numbers = shuffler.Shuffle(numbers).ToArray();
    
    // Display results.
    cards.Dump();
    numbers.Dump();

    // Perform a new shuffle using the same Shuffler instance.
    shuffler.Reshuffle();
    // Again use the Shuffler to shuffle the collections.
    cards = shuffler.Shuffle(cards).ToArray();
    numbers = shuffler.Shuffle(numbers).ToArray();

    // Display results.
    cards.Dump();
    numbers.Dump();
}

// You can define other methods, fields, classes and namespaces here
public class PictureBox
{
    public string Foo { get; set; }
}

public class Shuffler
{
    private List<Guid> order;
    private List<Guid> createOrder(int count)
    {
        return Enumerable.Range(0, count)
            .Select(i => Guid.NewGuid())
            .ToList();
    }
    
    public Shuffler(int count)
    {
        order = createOrder(count);
    }
    
    public void Reshuffle()
    {
        order = createOrder(order.Count);
    }
    
    public IEnumerable<T> Shuffle<T>(IEnumerable<T> collection)
    {
        return collection.Zip(order)
            .OrderBy(e => e.Second)
            .Select(e => e.First);
    }
}

A result set:

cards number
"12"  12
"1"   1
"0"   0
"11"  11
"3"   3
"2"   2
"9"   9
"5"   5
"10"  10
"8"   8
"4"   4
"7"   7
"6"   6

A purely static class with static fields and a Shuffle extension method could also have been made on the same principle.

  • Related