我是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”它。
非常感谢你。
编辑: 我应该澄清这是一个西班牙套牌,这就是没有杰克,女王,国王或王牌的原因
答案 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
您不必说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))
如您所见,我创建了一个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
哪个使用漂亮的迭代器,所以哇,太迷人了!
这些最后一个方法的问题在于,您无法确定是否将所有构造函数放在列表中,并且键入系统不会向您发出警告。 : - (