基本上,我有一个列表,每个数字都有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;
}
}
}
一个解决方案是将你的项目切割成多个部分。
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,数字相同),然后在最后对所有牌进行洗牌......。
我建议把你的循环改为迭代洗牌后的数字,而不是预期的网格大小。如果没有足够的牌,就像它一样,一些牌会被遗漏在网格的 "末端"。
然后,你可以使用除法和余数来计算出给定卡片索引的正确网格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);
}
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);