定义 OCaml 类型结构

defining OCaml type structure

我是 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

我想知道的是,是否有一种方法可以将一副牌定义为包含每个可用组合 palo - valor 的 carta 列表,然后 "shuffle" 它。

非常感谢您。

编辑: 我可能应该澄清一下,这是一套西班牙套牌,这就是为什么没有 Jack、Queen、King 或 Ace

嗯,当然,一个好的方法是 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

你不需要说 carta 是一个 Carta 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))

如您所见,我创建了一个勇士列表,对于每个 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

它使用迭代器,很漂亮,哇,太迷人了!

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