0
votes

I'm new with OCaml and I am trying to define a type to make a deck of cards, what I have now is:

type palo = Espada | Basto | Oro | Copa
type valor = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
type carta = Carta of palo*valor

what I want to know if there is a way in which I can define a deck as a list of carta with every combination palo - valor available and then "shuffle" it.

Thank you very much in advance.

Edit: I should probably clarify that this is a Spanish deck and that is why there is no Jack, Queen, King or Ace

1
Is your type valor really accepted ? I seriously doubt about it since it doesn't have the syntax : type t = C of type ;-)Lhooq
If the answer is ok for you, don't forget to accept it. ;-)Lhooq
@Lhooq how do I? Sorry but I'm also new to stackoverflow thank you the answer was greatJenaro Calviño
Don't you have something you can click on left to my answer ?Lhooq

1 Answers

3
votes

Well, you could, certainly, a good way to do it is a Fisher-Yates/Knuth shuffle

So, you would create an array of length 12 * 4 = 48 cards and then shuffle it (you can find this shuffle code in this page) and then use Array.to_list if you want to keep a list of cards and not an array.

[EDIT]

I took the liberty of rewriting your types :

type palo = Espada | Basto | Oro | Copa
type valor = Uno | Dos | Tres | Quatro | Cinco | Seis | Siete | 
             Ocho | Nueve | Diez | Once | Doce
type carta = palo * valor

You don't need to say that carta is a Carta of palo * valor since you have only one constructor ;-) carta will be an alias for the couple palo * valor.

But, actually, an easiest way to do would be to have the types :

type palo = Espada | Basto | Oro | Copa
type valor = int
type carta = palo * valor

and to ensure that your valor can't be greater than 12, for example. It would make the card creation much easier. (For example, doing so :

let cards = Array.init 48 (fun i -> 
   let palo = 
     if i < 12 then Espada
     else if i < 24 then Basto 
     else if i < 36 then Oro 
     else  Copa
   in palo, i mod 12 + 1
  )

)

[SECOND EDIT]

If you really want to have your valor types, this is one way to do :

type palo = Espada | Basto | Oro | Copa
type valor = Uno | Dos | Tres | Quatro | Cinco | Seis | Siete | 
             Ocho | Nueve | Diez | Once | Doce
type carta = palo * valor

let lv = [Uno; Dos; Tres; Quatro; Cinco; Seis; Siete; 
          Ocho; Nueve; Diez; Once; Doce]

let cards = 
  let new_list p = List.map (fun v -> p, v) lv in
  let l1 = new_list Espada in
  let l2 = new_list Basto in
  let l3 = new_list Oro in
  let l4 = new_list Copa in
  List.rev_append l1 (List.rev_append l2 (List.rev_append l3 l4))

As you can see, I created a list of valors and for each palo I add the palo to each element of this list (since lists are persistent data structures, it gives me a new list, it does not modify the previous one) and then I concatenate the four lists.

And an even better way to do :

let lp = [Espada; Basto; Oro; Copa]

let cardsb = 
  let new_list p = List.map (fun v -> p, v) lv in
  List.fold_left (fun acc p ->
    List.rev_append (new_list p) acc) [] lp

Which uses iterators which is beautiful, so wow, so charming !

The problem os these last methods is that you can't be sure that you put all your constructors in the list and the typing system won't warn you about it. :-(