Correctly using LINQ to shuffle a deck

人盡茶涼 提交于 2019-12-23 10:14:31

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!