FCards - Defining Cards

08. Taking from the deck

Taking card from the deck when picking up a card

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.

Exercise:

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.

See an answer

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; .... ]
  }

Code so far

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