What’s a popular single-player game that we can try - Solitaire, or course!
First we’ll list out some interesting bits of the Solitaire game:
Let’s start with dealing:
stacks
of cardsstack
stack
is face upstack
(even if they are face down)It may look something like:
| 1 | 2 | 3 | 4 | 5 | 6 |
[###] [###] [###] [###] [###] [♥A ]
[###] [###] [###] [###] [♥K ]
[###] [###] [###] [♦8 ]
[###] [###] [♠8 ]
[###] [♠Q ]
[♠10]
Deck: [[[[[[[[[[[[[[[[[[[[[[[[[###]
Note that now our model for a card in a stack is a bit more complex. Sometimes the card is face-up and sometimes it is face-down. We should incorporate that into our model (and make it easier for our future selves to print-out)
type StackCard = {
card: Card
isFaceUp: bool
} with
override this.ToString() =
if this.isFaceUp then
this.card.ToString()
else
"###"
Given that the model for our game would look like:
let Game = {
deck: Card list
table: Card list
stacks: StackCard list list
}
Write the dealing function that populates the deck and the stacks, leaving the table empty.
let deal shuffledDeck =
let emptyGame = {
deck = shuffledDeck
table = []
stacks = []
}
[6..-1..1] // a sequence of numbers from 6 to 1 in steps of -1 (i.e. backwards)
|> List.fold (fun game i ->
let newStack =
game.deck
|> List.take i
|> List.mapi // flip the last card
(fun n card -> { isFaceUp = (n = i - 1); card=card})
{
stacks = game.stacks @ [ newStack ]
deck = game.deck |> List.skip i
table = []
}
) emptyGame
// Load the contents of another file
#load "ch13_core.fsx"
// ... and then open the file's module (automatically prefixed with filename)
open Ch13_core.Core
module Solitaire =
open System
type StackCard = {
card: Card
isFaceUp: bool
} with
override this.ToString() =
if this.isFaceUp then
this.card.ToString()
else
"###"
type Game = {
deck: Card list
table: Card list
stacks: StackCard list list
}
let deal shuffledDeck =
let emptyGame = {
deck = shuffledDeck
table = []
stacks = []
}
[6..-1..1] // a sequence of numbers from 6 to 1 in steps of -1 (i.e. backwards)
|> List.fold (fun game i ->
let newStack =
game.deck
|> List.take i // flip the last card
|> List.mapi (fun n card -> { isFaceUp = (n = i - 1); card=card})
{
stacks = game.stacks @ [ newStack ]
deck = game.deck |> List.skip i
table = []
}
) emptyGame
;;
// DO IT!
newDeck
|> shuffle
|> Solitaire.deal