You may have noticed in chapter that when we took a card, that top card was still in the deck. The function returned a new updated hand but nothing else changed. The problem is that functions only return one thing, but the action of picking up a card changes two things: the hand and the deck.
So, rather than passing in a hand and a deck separately, we should combine these two things into a single Game thing.
Modify the pickupCard
function to use a combined Game
thing, including defining the Game
thing
(hint)
HINT: Define the Game as a record with a hand and a deck
TIP: I generally Prefer creating a record over a tuple, so that you can add names/labels to the parts for clarity - even if it is only two things.
type Game = {
deck: Card list
hand: Card list
}
let pickupCard (game: Game) =
match game.deck with
| [] -> failwith "No cards left!!!"
| [a] ->
{
hand = game.hand @ [a]
deck = []
}
| a::rest ->
{
hand = game.hand @ [a]
deck = rest
}
let after3Pickups =
{
hand = []
deck = newDeck
}
|> pickupCard
|> pickupCard
|> pickupCard
// result
{
hand = [ Hearts Two; Hearts Three; Hearts Four ]
deck = [ Hearts Five; .... ]
}
type CardNumber =
| Two
| Three
| Four
| Five
| Six
| Seven
| Eight
| Nine
| Ten
| Jack
| Queen
| King
| Ace
type Card =
| Hearts of CardNumber
| Diamonds of CardNumber
| Clubs of CardNumber
| Spades of CardNumber
| Joker
let newDeck =
let suits = [Hearts; Diamonds; Clubs; Spades]
let numbers = [
Two; Three; Four; Five; Six; Seven; Eight; Nine; Ten;
Jack; Queen; King; Ace
]
List.allPairs suits numbers
|> List.map (fun (suit, number) -> suit number)
type Game = {
deck: Card list
hand: Card list
}
let pickupCard (game: Game) =
match game.deck with
| [] -> failwith "No cards left!!!"
| [a] -> { hand = game.hand @ [a]; deck = [] }
| a::rest -> { hand = game.hand @ [a]; deck = rest }
;;
// DO IT!
{
deck = newDeck;
hand = [Hearts Three; Diamonds Ten; Clubs King; Joker]
}
|> pickupCard