Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using LINQ to shuffle a deck

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?

like image 799
jth41 Avatar asked Oct 05 '13 18:10

jth41


3 Answers

Use this extension method

public static class Extensions
{
    public static IEnumerable<T> Randomize<T>(this IEnumerable<T> source)
    {
        Random rnd = new Random();
        return source.OrderBy((item) => rnd.Next());
    }
}
like image 68
Masoud Darvishian Avatar answered Oct 18 '22 08:10

Masoud Darvishian


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.

like image 29
Display Name Avatar answered Oct 18 '22 09:10

Display Name


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.

like image 6
Sriram Sakthivel Avatar answered Oct 18 '22 08:10

Sriram Sakthivel