定义OCaml类型结构

时间:2016-04-27 14:47:09

标签: ocaml

我是OCaml的新手,我正在尝试定义一种类型来制作一副牌,我现在拥有的是:

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

我想知道的是,如果有一种方法我可以将牌组定义为一个carta列表,每个组合palo - valor可用,然后“shuffle”它。

非常感谢你。

编辑: 我应该澄清这是一个西班牙套牌,这就是没有杰克,女王,国王或王牌的原因

1 个答案:

答案 0 :(得分:3)

嗯,当然,你可以做一个好方法Fisher-Yates/Knuth shuffle

所以,你会创建一个长度为12 * 4 = 48卡的数组,然后将其洗牌(你可以在this page中找到这个随机播放代码)然后如果你想保留一个,则使用Array.to_list卡片列表而非数组。

[编辑]

我冒昧地重写你的类型:

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

您不必说cartaCarta of palo * valor,因为您只有一个构造函数;-) carta将成为情侣palo * valor的别名。

但实际上,最简单的方法是使用类型:

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

并确保你的勇气不能超过12。这将使卡片创建更容易。 (例如,这样做:

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
  )

[第二编辑]

如果你真的想拥有你的勇气类型,这是一种方法:

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))

如您所见,我创建了一个valors列表,并为每个palo我将palo添加到此列表的每个元素中(因为列表是持久数据结构,它给了我一个新列表,修改前一个)然后我连接四个列表。

还有更好的方法:

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

哪个使用漂亮的迭代器,所以哇,太迷人了!

这些最后一个方法的问题在于,您无法确定是否将所有构造函数放在列表中,并且键入系统不会向您发出警告。 : - (