我正在尝试使用 Fisher-Yates 算法来打乱一堆元素。我在通过引用传递堆栈时遇到问题。下面的代码给出了错误“迭代器不能有 ref 或 out 参数”。如何让算法对传入的实际堆栈起作用?
谢谢。
代码如下。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
public static class Doshuffle
{
public static IEnumerable<T> Shuffle<T>(ref Stack<T> source)
{
Random rng = new Random();
T[] elements = source.ToArray();
source.Clear();
// Note i > 0 to avoid final pointless iteration
for (int i = elements.Length - 1; i > 0; i--)
{
// Swap element "i" with a random earlier element it (or itself)
int swapIndex = rng.Next(i + 1);
T tmp = elements[i];
elements[i] = elements[swapIndex];
elements[swapIndex] = tmp;
}
// Lazily yield (avoiding aliasing issues etc)
foreach (T element in elements)
{
source.Push(element);
yield return element;
}
}
}
最佳答案
How do I get the algorithm to act on the actual stack that gets passed in?
您不需要需要 ref
自 Stack<T>
以来这里的参数是引用类型,您不会尝试重新分配引用本身。
默认情况下,引用是按值传递的,但该值(引用)指向堆上的同一个对象,换句话说,你有两个指向同一个对象的引用,这很好——所有操作都将在原始对象上执行Stack<T>
对象。
编辑:
根据您的评论,我建议您重新设计,不要修改原来的 Stack<T>
开始时很麻烦:
public static IEnumerable<T> Shuffle<T>(Stack<T> source)
{
Random rng = new Random();
T[] elements = source.ToArray();
// Note i > 0 to avoid final pointless iteration
for (int i = elements.Length - 1; i > 0; i--)
{
// Swap element "i" with a random earlier element it (or itself)
int swapIndex = rng.Next(i + 1);
T tmp = elements[i];
elements[i] = elements[swapIndex];
elements[swapIndex] = tmp;
}
// Lazily yield (avoiding aliasing issues etc)
foreach (T element in elements)
{
yield return element;
}
}
现在你可以像这样使用它:
foreach (var item in Doshuffle.Shuffle(gameDeck))
{
System.Console.WriteLine(item.cardName);
}
还要小心使用 Random
- 你可能想传入它。此时你可以使用 Jon Skeet's Shuffle implementation而不是您自己的 - 重用比重新发明更好。
最终编辑:
看起来你只是想洗牌你的 Stack<T>
就地——改用扩展方法:
public static void Shuffle<T>(this Stack<T> source)
{
Random rng = new Random();
T[] elements = source.ToArray();
source.Clear();
// Note i > 0 to avoid final pointless iteration
for (int i = elements.Length - 1; i > 0; i--)
{
// Swap element "i" with a random earlier element it (or itself)
int swapIndex = rng.Next(i + 1);
T tmp = elements[i];
elements[i] = elements[swapIndex];
elements[swapIndex] = tmp;
}
foreach (T element in elements)
{
source.Push(element);
}
}
现在你可以这样做:
gameStack.Shuffle();
关于时间:2019-03-08 标签:c#pass-by-referenceFisher-YatesShuffler,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7143100/