Как рандомизировать / перемешать два массива таким же образом в с #

У меня есть два массива, один из которых представляет собой массив PictureBox, а другой - массив Integer, оба имеют одинаковое количество элементов. Я хочу, чтобы оба массива каждый раз перетасовывались случайным образом, но оба перетасовывались одинаково.

Вот код, который работает, если я использую два массива PictureBox или два массива Integer, однако я хочу, чтобы он перемешивал один массив PictureBox и один массив Integer.

Это код, с которым я хочу работать: (два разных массива)

      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; 
}

Это код, который работает: (для тех же массивов)

      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; 
}

Если вы знаете другой код, который может помочь мне, не стесняйтесь поделиться им!

2 ответа

Просто создайте две временные переменные

      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; 
}

Если вам нужен перетасовщик, который можно использовать в любой коллекции, вы можете создать такой класс.

      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);
    }
}

Когда вы создаете экземпляр , внутри него создается список или псевдослучайные элементы (вот они Guids, но это могут быть случайно выбранные целые числа или что угодно). Чтобы перетасовать коллекцию, просто передайте ее методу. Каждая пройденная коллекция будет переупорядочена таким же образом.

Его можно было бы улучшить, например, он ожидает, что каждая коллекция будет иметь одинаковое количество элементов, и что это число было передано в Shufflerконструктор, это можно было бы ослабить. Также нет проверки ошибок, но она должна дать представление о принципе.

Вот пример использования. Вы можете попробовать это в 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);
    }
}

Набор результатов:

      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

Чисто статический класс со статическими полями и Shuffleметод расширения также мог бы быть выполнен по тому же принципу.

Другие вопросы по тегам