FCards - Solitaire

15. Displaying the stacks

Now that we have some stacks of cards, we can show them to the player. From last chapter we want it to look something like:

| 1  |  2  |  3  |  4  |  5  |  6  |
[###] [###] [###] [###] [###] [♥A ]
[###] [###] [###] [###] [♥K ]     
[###] [###] [###] [♦8 ]          
[###] [###] [♠8 ]               
[###] [♠Q ]                    
[♠10]                         

Deck:  [[[[[[[[[[[[[[[[[[[[[###]

Exercise:

Write the printScreen function that takes a Game and prints out the above.

See an answer

let printScreen game = 
  let maxCardInAnyStack = 
    game.stacks 
    |> List.map (fun stack -> stack.Length )
    |> List.max
  printfn "| 1  |  2  |  3  |  4  |  5  |  6  |"
  [0..maxCardInAnyStack - 1]
    |> List.iter (fun cardNum ->
      [0..5]
      |> List.map (fun stackNum ->
          if game.stacks[stackNum].Length > cardNum then 
            game.stacks[stackNum][cardNum]
            |> sprintf "[%O]"  // like printf, but to a string rather than the console
          else
            // the stack is out of cards
            "     "            
      )
      |> fun strings -> String.Join (" ", strings)
      |> printfn "%s"
  )
  //also print the remaining deck
  String.init game.deck.Length (fun _ -> "[")  
  |> printfn "\nDeck:  %s###]"

Code so far

#load "ch13_core.fsx"
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] 
    |>  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

  let printScreen game = 
    let maxCardInAnyStack = 
      game.stacks 
      |> List.map (fun stack -> stack.Length )
      |> List.max
    printfn "| 1  |  2  |  3  |  4  |  5  |  6  |"
    [0..maxCardInAnyStack - 1]
      |> List.iter (fun cardNum ->
        [0..5]
        |> List.map (fun stackNum ->
            if game.stacks[stackNum].Length > cardNum then 
              game.stacks[stackNum][cardNum]
              |> sprintf "[%O]"
            else
              // the stack is out of cards
              "     "            
        )
        |> fun strings -> String.Join (" ", strings)
        |> printfn "%s"
    )
    //also print the remaining deck
    String.init game.deck.Length (fun _ -> "[")  
    |> printfn "\nDeck:  %s###]"



;;
// DO IT!
newDeck 
|> shuffle 
|> Solitaire.deal 
|> Solitaire.printScreen