洗牌<T>
Shuffling a Stack<T>
public static void Shuffle<T> ( this Stack<T> stack )
{
List<T> list = stack.ToList ();
list.Shuffle ();
stack = list.ToStack ();
}
public static void Shuffle<T> ( this List<T> list )
{
for ( int i = 0; i < list.Count; i++ )
{
int num = Form1.rnd.Next ( list.Count );
T temp = list[i];
list[i] = list[num];
list[num] = temp;
}
}
public static Stack<T> ToStack<T> ( this List<T> list )
{
Stack<T> stack = new Stack<T> ();
foreach ( T t in list )
stack.Push ( t );
return stack;
}
以上是我对通用堆栈进行洗牌的尝试。但是,尽管 List Shuffle 扩展方法有效,但 Stack Shuffle 无法按预期工作。就好像中间的 Shuffle 调用根本就没有调用一样。相反,它仍然是相同的列表,未改组。所以我认为问题出在 ToStack 函数中。有人可以解释我的错误吗?提前致谢!
Shuffle
方法(采用 Stack<T>
)按值获取堆栈参数。因此,当您调用 stack = list.ToStack ();
时,您正在更改方法本地的变量 (stack
)。
一个解决方案是像您使用 List<T>
洗牌方法那样做:
public static Stack<T> Shuffle<T>(this Stack<T> stack)
{
List<T> list = stack.ToList();
list.Shuffle();
return list.ToStack();
}
此方法将堆栈作为输入生成新的混洗堆栈。你可以这样使用它:
Stack<int> stack = new Stack<int>();
for(int i = 0 ; i < 10 ; i++)
stack.Push(i);
stack = stack.Shuffle();
问题是您将 Stack<T>
的新实例分配给局部变量,这意味着调用堆栈变量未更改。
现在您可以向参数添加 ref
,但我通常会尽量避免这样做。
这里有两种选择。
如果您想继续使用相同的引用,那么您可以这样做:
public static void Shuffle<T>(this Stack<T> stack)
{
var values = stack.ToArray();
stack.Clear();
foreach (var value in values.OrderBy(x => rnd.Next()))
stack.Push(value);
}
这相当简单,无需调用单独的方法来随机播放。
或者,您可以 return Stack<T>
的新实例。
public static Stack<T> Shuffle<T>(this Stack<T> stack)
{
return new Stack<T>(stack.OrderBy(x => rnd.Next()));
}
这再次避免了调用单独的 shuffle 方法的需要。
这两种方法都使用 .OrderBy(x => rnd.Next())
执行洗牌,这比交换索引要容易得多。
public static void Shuffle<T> ( this Stack<T> stack )
{
List<T> list = stack.ToList ();
list.Shuffle ();
stack = list.ToStack ();
}
public static void Shuffle<T> ( this List<T> list )
{
for ( int i = 0; i < list.Count; i++ )
{
int num = Form1.rnd.Next ( list.Count );
T temp = list[i];
list[i] = list[num];
list[num] = temp;
}
}
public static Stack<T> ToStack<T> ( this List<T> list )
{
Stack<T> stack = new Stack<T> ();
foreach ( T t in list )
stack.Push ( t );
return stack;
}
以上是我对通用堆栈进行洗牌的尝试。但是,尽管 List Shuffle 扩展方法有效,但 Stack Shuffle 无法按预期工作。就好像中间的 Shuffle 调用根本就没有调用一样。相反,它仍然是相同的列表,未改组。所以我认为问题出在 ToStack 函数中。有人可以解释我的错误吗?提前致谢!
Shuffle
方法(采用 Stack<T>
)按值获取堆栈参数。因此,当您调用 stack = list.ToStack ();
时,您正在更改方法本地的变量 (stack
)。
一个解决方案是像您使用 List<T>
洗牌方法那样做:
public static Stack<T> Shuffle<T>(this Stack<T> stack)
{
List<T> list = stack.ToList();
list.Shuffle();
return list.ToStack();
}
此方法将堆栈作为输入生成新的混洗堆栈。你可以这样使用它:
Stack<int> stack = new Stack<int>();
for(int i = 0 ; i < 10 ; i++)
stack.Push(i);
stack = stack.Shuffle();
问题是您将 Stack<T>
的新实例分配给局部变量,这意味着调用堆栈变量未更改。
现在您可以向参数添加 ref
,但我通常会尽量避免这样做。
这里有两种选择。
如果您想继续使用相同的引用,那么您可以这样做:
public static void Shuffle<T>(this Stack<T> stack)
{
var values = stack.ToArray();
stack.Clear();
foreach (var value in values.OrderBy(x => rnd.Next()))
stack.Push(value);
}
这相当简单,无需调用单独的方法来随机播放。
或者,您可以 return Stack<T>
的新实例。
public static Stack<T> Shuffle<T>(this Stack<T> stack)
{
return new Stack<T>(stack.OrderBy(x => rnd.Next()));
}
这再次避免了调用单独的 shuffle 方法的需要。
这两种方法都使用 .OrderBy(x => rnd.Next())
执行洗牌,这比交换索引要容易得多。