присвоение GameObjects списку и присвоение им индекса - PullRequest
1 голос
/ 06 мая 2020

В общем, у меня есть список с двумя числами каждого числа, и я хочу случайным образом назначить одно из этих чисел каждой карте, которая создается. Это игра-головоломка для запоминания, где вы находите совпадения.

Игра работает нормально, когда у меня есть 2 gridRows и 4 gridCols, но если я изменю количество строк или столбцов, я получу: ArgumentOutOfRangeException: Index was вне зоны доступа. Должен быть неотрицательным и быть меньше размера коллекции. Название параметра: index, что не дает мне расширить игру. Я попытался добавить дополнительные числа в текущий список, но это, похоже, не сработало, а также этот способ не кажется очень эффективным, если я хочу иметь много строк и столбцов

Что я хочу сделать это взять список, затем перетасовать его содержимое каждый раз, когда я начинаю сопоставление, а затем до l oop через индексы по порядку (содержимое уже перемешано), когда я создаю экземпляр, это мой logi c, но не смог заставить его работать по какой-то причине ....

может кто-нибудь помочь мне расширить это и найти лучший способ хранения индекса, пожалуйста?

вот код:

 public const int gridRows = 2;
public const int gridCols = 4;
public const float offsetX = 4f;
public const float offsetY = 5f;

public MainCard originalCard;
public Sprite[] images;


private void Start()
{
    Vector3 startPos = originalCard.transform.position;
    List<int> numbers = new List<int> { 0, 0, 1, 1, 2, 2, 3, 3 };
    numbers = Shuffle(numbers);

    for (int i = 0; i < gridCols; i++)
    {
        for (int x = 0; x < gridRows; x++)
        {
            MainCard card;
            if (i == 0 && x == 0)
            {
                card = originalCard;
            }
            else
            {
                card = Instantiate(originalCard) as MainCard;
            }

            int index = x * gridCols + i;
            int id = numbers[index];
            card.ChangeSprite(id, images[id]);

            float posX = (offsetX * i) + startPos.x;
            float posY = (offsetX * x) + startPos.y;
            card.transform.position = new Vector3(posX, posY, startPos.z);
        }
    }

    List<T> Shuffle<T>(List<T> cards)
    {
        for (int i = 0; i < cards.Count; i++)
        {
            T temp = cards[i];
            int randomIndex = Random.Range(i, cards.Count);
            cards[i] = cards[randomIndex];
            cards[randomIndex] = temp;
        }

        return cards;
    }

}

}

Ответы [ 3 ]

0 голосов
/ 06 мая 2020

Я бы посоветовал изменить l oop для перебора перемешанных чисел, а не ожидаемого размера сетки. Если карточек не хватает, как бы то ни было, некоторые будут пропущены в «конце» сетки.

Затем вы можете использовать деление и остаток, чтобы вычислить правильные координаты X / Y сетки для данная картотека.

for (int i = 0; i < numbers.Length; i++) {
    int y = Math.Floor(i / gridCols);  // the floor is likely redundant but drives the point home
    int x = i % gridCols;
    var card = (i == 0 ? originalCard : Instantiate(originalCard) as MainCard);
    int id = numbers[i];
    card.ChangeSprite(id, images[id]);
    float posX = (offsetX * y) + startPos.x;
    float posY = (offsetY * x) + startPos.y;
    card.transform.position = new Vector3(posX, posY, startPos.z);
}
0 голосов
/ 06 мая 2020

EDIT: Nevermind, как кто-то сказал в комментарии Random.Range эксклюзивен для целых чисел

Я вообще не знаю, может ли это вызывать вашу проблему, но я заметил, что в вашем методе Shuffle вы имейте эту строку:

int randomIndex = Random.Range(i, cards.Count);

На мой взгляд, это может вызвать ошибку, потому что максимальное значение в Random.Range является включительным, поэтому возможно, что вы создаете недопустимый индекс для некоторых карт.

Например, если у вас есть список из 5 карточек, максимальный индекс, который вы хотели бы создать, будет 4, а не 5 (это будет счетчик).

Я бы попытался изменить эту строку на эту:

int randomIndex = Random.Range(i, cards.Count-1);
0 голосов
/ 06 мая 2020

Одно из решений - разрезать ваш проект на несколько частей:

using System.Linq;//to Add

public int gridRows = 2;
public  int gridCols = 4;
public List<int> numbers;
public void Start()
{
    int[,] cards = new int[gridRows, gridCols];
    //just put different numbers not needed to duplicate 
    //except if you want to increase the probability
    // to have lot of same number
    numbers = new List<int> { 0, 1, 2, 3 };
    InitializeGame(cards);
}

private void InitializeGame(int[,] cards)
{
    //1 you could shuffle your number if you want
    //numbers = Shuffle(numbers);

    //2 you initialize cards to value not used (-1 here)
    for (int r = 0; r < gridRows; r++)
    {
        for (int c = 0; c < gridCols; c++)
        {
            cards[r, c] = -1;
        }
    }

    // Test if you have filled up all cards
    //Is there again one card with the value -1?
    while (cards.Cast<int>().Any(x => x == -1))
    {
        //3 you pick randomnly a number
        var numCard = numbers[Random.Range(0, numbers.Count)];

        //4 you fill same number to 2 different cards here
        var nbcardTofill = 2;
        while (nbcardTofill != 0)
        {
            //you choose randomny card (row and col) which is free (value = -1) not need but add fun
            var colRandom = Random.Range(0, gridCols);
            var rowRandom = Random.Range(0, gridRows);
            if(cards[rowRandom, colRandom] == -1)
            {
                nbcardTofill--;
                cards[rowRandom, colRandom] = numCard;
            }
        }
    }
}

теперь у вас есть карточки массива, заполненные числами, теперь вы можете нарисовать игру ..

, чтобы вы могли измените количество столбцов / строк и список чисел, как хотите ...

- это всего лишь один из способов программирования, но я думаю, что он более читабельный. Я добавил много рандомизации, чтобы добавить веселья ...

Другой способ - последовательно заполнить ваши карты (2 на 2 с тем же номером) и перетасовать все карты в конце ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...