定义 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 是您无法确定是否将所有构造函数都放在列表中,并且键入系统不会就此发出警告。 :-(
我是 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 是您无法确定是否将所有构造函数都放在列表中,并且键入系统不会就此发出警告。 :-(