问题
I am attempting to write a simple card game. In an effort to come up with a good shuffling algorithm I came across Jeff Atwood's post on Coding Horror.
However When I view the contents of the object after calling the Constructor they are not shuffled.
Here is my attempt to use Jeff's Solution:
class MainDeck : List<Card>
{
public MainDeck()
{
this.Add(new Card(1, "Hearts"));
this.Add(new Card(2, "Hearts"));
this.Add(new Card(3, "Hearts"));
...
this.OrderBy(a => Guid.NewGuid());
}
}
here is the code for Card:
class Card
{
string suit;
int value;
public Card(int value, string suit)
{
this.value = value;
this.suit = suit;
}
bool isFaceCard()
{
if (value >= 11 || value == 1)
return true;
else
return false;
}
public override string ToString()
{
return (value +", " + suit);
}
}
What should I change to make the shuffling work?
回答1:
LINQ methods are not mutating existing collections. So this statement does nothing at all: this.OrderBy(a => Guid.NewGuid());
Also, I'm pretty sure you can't assign to this
, so you have to either don't inherit from List<T>
(which is good), or do something like this:
var sorted = this.OrderBy(a => Guid.NewGuid()).ToList();
this.Clear();
this.AddRange(sorted);
Also look at this SO answer, there is more correct shuffling algorithm.
回答2:
Use this extension method
public static IEnumerable<T> Randomize<T>(this IEnumerable<T> source)
{
Random rnd = new Random();
return source.OrderBy<T, int>((item) => rnd.Next());
}
回答3:
Try this
public void Shuffle()
{
Random r = new Random();
this.Sort((x, y) => r.Next(-1, 1));
}
Because of Linq's deffered execution following line doesn't get executed.
this.OrderBy(a => Guid.NewGuid());
This just creates the query but never executed. Even if executed it won't change your collection.
Don't forget Linq is a way to query data, not mutate it.
回答4:
Linq does not work by reference.
you should get the result into a variable. Create the list object inside the class instead of inheriting from the list as follows:
class MainDeck
{
public List<Card> lstCards;
public MainDeck()
{
this.lstCards.Add(new Card(1, "Hearts"));
this.lstCards.Add(new Card(2, "Hearts"));
this.lstCards.Add(new Card(3, "Hearts"));
...
this.lstCards = this.lstCards.OrderBy(a => Guid.NewGuid()).ToList();
}
}
Please mark as answer or helpful if this answer helps.
来源:https://stackoverflow.com/questions/19201489/correctly-using-linq-to-shuffle-a-deck