# F# Card Game Part 2 - Dealing Cards

Friday, May 20, 2016

In part one of this series we walked through modeling the domain of our card game. In this post we'll use that domain as a guide to help us create a deck, shuffle the deck, and deal cards from the deck.

### Creating the deck

There may be more elegant ways to do this, but for now we'll simply define a value and populate it with the cards.

```
let newDeck =
[(Two, Spades); (Three, Spades); (Four, Spades); (Five, Spades);
(Six, Spades); (Seven, Spades); (Eight, Spades); (Nine, Spades);
(Ten, Spades); (Jack, Spades); (Queen, Spades); (King, Spades); (Ace, Spades);
(Two, Hearts); (Three, Hearts); (Four, Hearts); (Five, Hearts);
(Six, Hearts); (Seven, Hearts); (Eight, Hearts); (Nine, Hearts);
(Ten, Hearts); (Jack, Hearts); (Queen, Hearts); (King, Hearts); (Ace, Hearts);
(Two, Clubs); (Three, Clubs); (Four, Clubs); (Five, Clubs);
(Six, Clubs); (Seven, Clubs); (Eight, Clubs); (Nine, Clubs);
(Ten, Clubs); (Jack, Clubs); (Queen, Clubs); (King, Clubs); (Ace, Clubs);
(Two, Diamonds); (Three, Diamonds); (Four, Diamonds); (Five, Diamonds);
(Six, Diamonds); (Seven, Diamonds); (Eight, Diamonds); (Nine, Diamonds);
(Ten, Diamonds); (Jack, Diamonds); (Queen, Diamonds); (King, Diamonds); (Ace, Diamonds)]
```

Because this value is immutable (the default in F#), we don't have to make a function that returns a new `Card list`

. No function can modify our `newDeck`

value in any way; it will always be exactly the same value.

*Notice I'm continuing to use the term "value" rather than "variable". These values cannot vary once they are assigned. This concept is paramount to the entire series.*

### Shuffling the deck

Now that we have the concept of a full deck we need to introduce some way to shuffle the deck to produce a random order of cards so that each game is different. Of course, our `newDeck`

value is immutable so what we'll actually do is return a new `Card list`

that is shuffled rather than actually modifying the `newDeck`

value.

```
let shuffle deck =
let random = new System.Random()
deck |> List.sortBy (fun card -> random.Next())
```

If we hover over `shuffle`

we'll see that it is a function that takes a `'a list`

and returns an `'a list`

. The default for F#'s type inference is to be generic as possible. In the anonymous function we passed into `List.sortBy`

we didn't use the `card`

argument at all so we now have a function that could actually be used to randomly sort any kind of list.

*I'm aware that System.Random() is probably not the best choice for generating "true randomness" but that's not the point of this post.*

To test it out we can easily run it in our REPL

```
newDeck |> shuffle
//val it : (Rank * Suit) list =
// [(King, Spades); (Four, Clubs); (Ace, Clubs); (Four, Hearts); (Ten, Clubs);
...
```

And for proof that no values were harmed during the shuffle process you could evaluate `newDeck`

again and see that it is still the same value it was before.

```
newDeck
//val it : (Rank * Suit) list =
// [(Two, Spades); (Three, Spades); (Four, Spades); (Five, Spades);
```

### Dealing a card

Now that we can create a shuffled deck we need some way of dealing a card. If our shuffled deck were a mutable list like a javascript array we would probably call `pop`

which would return the first element in the array and mutate the array so that the returned element is no longer part of the array.

The immutable way of dealing a card is to do what's known as a `head::tail pattern match`

. We destructure the list into a `head`

, which is the first element of the list, and a `tail`

which is the rest of the list. That allows us to easily return the drawn card and a new list of cards that can represent the remaining deck.

```
let deal deck =
match deck with
| head::tail -> (head, tail)
| [] -> //handle empty list
```

In any `match`

statement F# forces you to be complete; you must explicitly handle every case that can exist. If I hadn't handled the empty list scenario the compiler would tell me that I had an incomplete pattern match and suggest cases that I hadn't handled.

In the case that we have a non empty list our implementation is quite easy. We return a tuple of the top card and the remaining cards. But what should we do in the case of an empty list?

A functional approach to handling the error state would be to introduce the `Option`

type.

```
let deal deck =
match deck with
| head::tail -> (Some head, tail)
| [] -> (None, [])
```

Looking at the `deal`

function's signature we can see that it takes an `'a list`

and returns a tuple of an `'a option`

and an `'a list`

. **This is honest code.** It says, I'll try to return you the top card, but I can't guarantee it because you could hand me an empty list.

```
newDeck |> shuffle |> deal;;
val it : (Rank * Suit) option * (Rank * Suit) list =
(Some (Seven, Clubs),
[(Two, Hearts); (King, Spades); (Five, Clubs); (Eight, Spades);
...
```

### 52 card pick up

An easy way to prove that our deal function does what we'd expect is to draw all the cards in the deck. In a functional sense what that means is that we want to use a recursive function to loop through the deck.

```
let rec dealAllCards deck =
let (card, remainingDeck) = deck |> deal
match card with
| None -> printfn "Cards out"
| Some c ->
printfn "%A" c
remainingDeck |> dealAllCards
```

The `rec`

directive tells F# that the function is a recursive function and is allowed to call itself. The name of our function is `dealAllCards`

and it takes one argument which is a `Card list`

In the first line `let (card, remainingDeck) = deck |> deal`

we're destructuring the tuple returned from our `deal`

function into a `card`

value and a `remainingDeck`

value.

Because our `card`

value is an option type our next step is to match on it to determine our next step.

If our `deal`

function was not able to return a card (the `None`

case) we print "Cards out" to the console.

If our `deal`

function returned a card (the `Some c`

case) we print the card to the console and then recursively call the function with the `remainingDeck`

value.

Running our function in the REPL proves our code works

```
newDeck |> shuffle |> dealAllCards
//(Five, Diamonds)
//(Six, Hearts)
//(Six, Clubs)
//...
//Cards out
```