将GameObjects分配给一个列表,并给它们一个索引。

问题描述 投票:0回答:1

基本上,我有一个列表,每个数字都有2个,我想把这些数字中的一个随机分配给每个被实例化的卡片。这是一个拼图记忆游戏,你要找到匹配的数字。

当我有2个gridRows和4个gridCols时,游戏运行得很好,但如果我改变行或cols的数量,我就会得到。"ArgumentOutOfRangeException: Index was out of range. 必须是非负数,并且小于集合的大小。参数名称:索引,这使我无法扩展游戏。我试过在当前列表中添加额外的数字,但似乎并不奏效,而且如果我想拥有大量的行和列,这种方式似乎也不是很有效率。

我想做的是取一个列表,然后在每次开始匹配时对其内容进行洗牌,然后在实例化时按顺序循环索引(内容已洗牌),这是我的逻辑,但由于某些原因无法使其工作......

谁能帮我扩展一下,找一个更好的方法来存储索引?

下面是代码。

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

}

}

c# oop unity3d
1个回答
0
投票

一个解决方案是将你的项目切割成多个部分。

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

现在你的数组卡片上已经填满了数字,你可以画出游戏...

所以你可以改变colsrows的数量和数字列表,因为你想... ...

这只是一种编程方式,但我认为它更容易读懂。

另一种方法是按顺序填满你的牌(2乘2,数字相同),然后在最后对所有牌进行洗牌......。


0
投票

我建议把你的循环改为迭代洗牌后的数字,而不是预期的网格大小。如果没有足够的牌,就像它一样,一些牌会被遗漏在网格的 "末端"。

然后,你可以使用除法和余数来计算出给定卡片索引的正确网格XY坐标。

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
投票

EDIT: 算了,正如有人在评论中所说的那样,Random.Range对整数是排斥的。

我不知道这是否会导致你的问题,但是我注意到在你的Shuffle方法中有这样一行。

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

在我看来,这可能会导致一个错误,因为Random.Range中的最大值是包含性的,所以有可能你为一些卡片生成了一个无效的索引。

例如,如果你有一个有5张牌的列表,你想生成的最大索引应该是4,而不是5(这应该是Count)。

我可以试着把这一行改成这样。

int randomIndex = Random.Range(i, cards.Count-1);
© www.soinside.com 2019 - 2024. All rights reserved.