Reputation: 193
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
Upvotes: 0
Views: 203
Reputation: 4441
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.
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
)
)
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. :-(
Upvotes: 3