列表中的 ArgumentsOutOfRangeExeption<T>
ArgumentsOutOfRangeExeption in a list<T>
我在调用该方法时抛出此异常。该列表恰好包含 52 个对象(卡片数量)。
有什么建议可能导致它吗?也许是 Add 和 RemoveAt 方法?或者也许是随机的?
编译器还告诉问题出在 deck.Add(temp[j]);线.
public void Shuffle()
{
List<Card> temp = new List<Card>();
Random rand = new Random();
for (int i = 0; i < 52; i++)
{
for (int j = rand.Next(i, 52); j < 52; j++)
{
temp.Add(deck[j]);
deck.RemoveAt(j);
deck.Add(temp[j]);
}
}
}
temp[j]
不一定存在。您需要初始化 temp
以便它至少有 j
+1 个条目,或者您需要将 temp[j]
的行更改为更合适的内容。
当您调用 rand.Next(i, 52)
时,结果可能是 52,这将超出您的牌组和临时牌组的范围。
此外,正如@nvoigt 指出的那样,您需要初始化 temp
列表。 List
有一个构造函数,它接受一个整数作为初始大小。您可以传入 52。请参阅:http://msdn.microsoft.com/en-us/library/dw8e0z9z(v=vs.110).aspx.
您也可以通过在调试器中查看 j
的值自行轻松调试。
如果您想打乱项目列表,可以使用以下方法:
public static void Shuffle<T>(IList<T> arr, Random rnd)
{
for (var i = 0; i < arr.Count; i++)
{
var j = rnd.Next(i, arr.Count);
var tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}
此方法将帮助您在没有 ArgumentsOutOfRangeExeption 的情况下洗牌
好的,让我们假设我们正处于循环的第一个 运行。外循环和内循环的第一次迭代。 i
是 0
,Rand(i, 52)
产生 13
。
所以我们有:
i - 0
j - 13
temp - empty list
deck - assume this is a list with 52 elements
现在让我们运行循环内的三行代码:
temp.Add(deck[j]);
获取deck
的第13项,并将其添加到temp
。 OK完成。 temp
现在有 1 个项目。
deck.RemoveAt(j);
删除 deck
中的第 13 项。好的,好的。
deck.Add(temp[j]);
获取 temp
中的第 13 项并将其添加到,等等,什么?1? temp
只有1件商品! Exception
! Exception
!.
首先不需要 temp
列表。有一个 very good shuffling algorithm 涉及遍历原始项目列表一次(而不是 N 次)。你只需要一个 temp
变量来保存一个值,同时将它与另一个交换。像这样:
public void Shuffle()
{
Card temp;
Random rand = new Random();
for (int i = deck.Length; i >= 1; i--)
{
int j = rand.Next(0, i + 1);
temp = deck[i];
deck[i] = deck[j];
deck[j] = temp;
}
}
完成。
我在调用该方法时抛出此异常。该列表恰好包含 52 个对象(卡片数量)。 有什么建议可能导致它吗?也许是 Add 和 RemoveAt 方法?或者也许是随机的? 编译器还告诉问题出在 deck.Add(temp[j]);线.
public void Shuffle()
{
List<Card> temp = new List<Card>();
Random rand = new Random();
for (int i = 0; i < 52; i++)
{
for (int j = rand.Next(i, 52); j < 52; j++)
{
temp.Add(deck[j]);
deck.RemoveAt(j);
deck.Add(temp[j]);
}
}
}
temp[j]
不一定存在。您需要初始化 temp
以便它至少有 j
+1 个条目,或者您需要将 temp[j]
的行更改为更合适的内容。
当您调用 rand.Next(i, 52)
时,结果可能是 52,这将超出您的牌组和临时牌组的范围。
此外,正如@nvoigt 指出的那样,您需要初始化 temp
列表。 List
有一个构造函数,它接受一个整数作为初始大小。您可以传入 52。请参阅:http://msdn.microsoft.com/en-us/library/dw8e0z9z(v=vs.110).aspx.
您也可以通过在调试器中查看 j
的值自行轻松调试。
如果您想打乱项目列表,可以使用以下方法:
public static void Shuffle<T>(IList<T> arr, Random rnd)
{
for (var i = 0; i < arr.Count; i++)
{
var j = rnd.Next(i, arr.Count);
var tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}
此方法将帮助您在没有 ArgumentsOutOfRangeExeption 的情况下洗牌
好的,让我们假设我们正处于循环的第一个 运行。外循环和内循环的第一次迭代。 i
是 0
,Rand(i, 52)
产生 13
。
所以我们有:
i - 0
j - 13
temp - empty list
deck - assume this is a list with 52 elements
现在让我们运行循环内的三行代码:
temp.Add(deck[j]);
获取deck
的第13项,并将其添加到temp
。 OK完成。 temp
现在有 1 个项目。
deck.RemoveAt(j);
删除 deck
中的第 13 项。好的,好的。
deck.Add(temp[j]);
获取 temp
中的第 13 项并将其添加到,等等,什么?1? temp
只有1件商品! Exception
! Exception
!.
首先不需要 temp
列表。有一个 very good shuffling algorithm 涉及遍历原始项目列表一次(而不是 N 次)。你只需要一个 temp
变量来保存一个值,同时将它与另一个交换。像这样:
public void Shuffle()
{
Card temp;
Random rand = new Random();
for (int i = deck.Length; i >= 1; i--)
{
int j = rand.Next(0, i + 1);
temp = deck[i];
deck[i] = deck[j];
deck[j] = temp;
}
}
完成。