【问题标题】:How to get a random value for a custom datatype in SML?如何在 SML 中获取自定义数据类型的随机值?
【发布时间】:2021-01-24 04:30:34
【问题描述】:

如何为如下数据类型返回随机值?

datatype rank = Jack | Queen | King | Ace | Num of int

我正在研究一个函数,生成一个随机卡片列表以输入到另一个函数,因此也需要一个类似的函数来进行花色。

输出应该是 Jack、King 等符号,或者是从 2 到 9 的 int。

下面的代码不正确:

fun pick_rank() =
   case Random.randRange(2,13)  of 13 => Ace
               | 12 => King
               | 11 => Queen
               | 10 => Jacl
               | Int v => v

【问题讨论】:

标签: sml smlnj


【解决方案1】:

如何为如下数据类型返回随机值?

datatype rank = Jack | Queen | King | Ace | Num of int

我有两个答案:要么生成唯一的每个值,要么生成所有可能的值,将它们打乱并选择一个。如果你只是想要一个孤立的随机变量,前者是最简单的。但是如果你想模拟一个纸牌游戏,其中不可能两次抽取同一张牌,那么你可能需要洗牌。

您可以看到我是如何制作command-line blackjack game 的。我将在这里重复这两种方法:

(* There are 13 card ranks, 4 suits *)
datatype rank
  = Ace | Two | Three | Four | Five | Six | Seven
  | Eight | Nine | Ten | Jack | Queen | King

datatype suit = Hearts | Clubs | Diamonds | Spades

datatype card = Card of suit * rank

fun concatMap f xs = List.concat (List.map f xs)
fun product xs ys = concatMap (fn x => map (fn y => (x,y)) ys) xs

val allCards = map Card
  (product
     [Hearts,Clubs,Diamonds,Spades]
     [Ace,Two,Three,Four,Five,Six,Seven,Eight,Nine,Ten,Jack,Queen,King])

(* Create a new pseudo-random number generator, prng *)
val prng = Random.newgen ()

(* rlist determines a random index in [0 ; length xs[. *)
fun rlist xs = Random.range (0, length xs) prng

(* remove removes the n'th element of a list *)
fun remove (_, []) = raise Domain
  | remove (0, card::library) = library
  | remove (n, card::library) = card::remove (n-1, library);

(* randomtake removes and returns the i'th (random) element of a list *)
fun randomtake library =
    let val i = rlist library
        val card = List.nth (library, i)
        val rest = remove (i, library)
    in
      (card, rest)
    end

(* Shuffling is done by removing random cards until there are no cards left *)
fun shuffle [] = []
  | shuffle cards =
    let val (c,r) = randomtake cards
    in
      c :: shuffle r
    end

使用这些函数,您可以通过 randomtake allCards 随机选择一张卡片,或者您可以通过第一个 shuffle allCards 选择任意数量的随机卡片而不选择同一张卡片,然后选择最上面的元素。

请注意,这些不是有效的方法。作为练习,您可以实现Fisher-Yates shuffle

【讨论】:

  • 能否仅举一个花色 = 黑桃 | 的例子?俱乐部 |心 |钻石?我想我可以按原样使用代码,只需用花色*等级形式的卡片填写列表 n 次。
  • 该示例表明当前示例没有演示什么?
猜你喜欢
  • 1970-01-01
  • 2021-02-15
  • 2014-07-19
  • 2017-09-29
  • 2023-03-14
  • 1970-01-01
  • 2014-04-29
  • 2019-05-12
相关资源
最近更新 更多