2014-11-04 78 views
4

建模擲骰我使用F#做的擲骰一些Monte Carlo模擬,我使用整數來表示一個骰子的單輥和整數列表來表示擲骰的列表。我希望能夠將骰子滾動而不是整數模型化爲一種類型。我只使用6面骰子,我想要一種具有別名/同義詞類型的特徵的類型以及歧視聯盟或枚舉的一些屬性。在F#

這是我希望看到我的類型

  1. 我喜歡的類型表現得像一個整數,所以我可以最大/最小/和/列表上的摺疊什麼。
  2. 我希望類型能夠被分配爲一個整數值。
  3. 我想類型被約束至1-6,使得可以存在零的沒有骰子輥和7的沒有骰子翻滾。

我已經嘗試了上面列出的類型的組合,並且都似乎有一些退後(這可能是我的用法和理解,而不是類型本身)。

這是什麼我做的樂趣(不是利潤),但想看看我能想象的更嚴重的數據建模使用這個答案只是一個簡單的例子。

+0

只是好奇:你是 '琢磨' 擲骰? :) – Mau 2014-11-04 14:37:18

+0

通常的做法是創建一個沒有導出構造函數的類型,然後創建一個函數'int - > DiceRoll選項,如果參數超出範圍,它將不返回任何內容。然後,您可以創建一個函數'DiceRoll - > int'來提取值並添加您想要支持的任何運算符。 – Lee 2014-11-04 14:44:20

+0

我參加了MOOC https://www.edx.org/course/mitx/mitx-11-126x-introduction-game-design-2881,我在玩骰子計算規則,創造出有趣的概率分佈,但是玩家難以推理(而不是簡單地擲骰子)。 – AlexC 2014-11-04 15:22:47

回答

3

這似乎是一個可識別聯合一些靜態方法可以處理你想要的一切

open System 

type D6 = 
    | One | Two | Three | Four | Five | Six 

    member self.Value = 
     match self with 
     | One -> 1  | Two -> 2  | Three -> 3 
     | Four -> 4  | Five -> 5  | Six -> 6 

    override self.ToString() = 
     match self with 
     | One -> "One" | Two -> "Two" | Three -> "Three" 
     | Four -> "Four" | Five -> "Five" | Six -> "Six" 

    static member Create (num:int) = 
     match num with 
     | 1 -> One | 2 -> Two | 3  -> Three 
     | 4 -> Four | 5 -> Five | 6  -> Six  
     | _ -> failwithf "Could not create D6, %d is not in range 1-6" num 

    static member inline Roll() = Random().Next(1,7) |> D6.Create 

調用D6。卷()會產生一個隨機卷

> D6.Roll();; val it : D6 = Four

> D6.Roll();; val it : D6 = Six

> D6.Roll();; val it : D6 = Two

> D6.Roll();; val it : D6 = Five

您可以創建靜態成員和運營商,可以輕鬆譜寫自己的D6s一起

static member inline Add  (a:D6) (b:D6) = a.Value + b.Value 
    static member inline (+)  (a , b ) = D6.Add a b 
    static member inline Subtract (a:D6) (b:D6) = a.Value - b.Value 
    static member inline (-)  (a , b ) = D6.Subtract a b 

和靜態成員,可以很容易從輸入列表創建它們

static member FromList (numls: int list) = 
     numls |> List.map D6.Create 

比較開箱這類

D6.One > D6.Two;; val it : bool = false

D6.One < D6.Two;; val it : bool = true

無限序列使很容易產生隨機輸入

let rollGen = 
    let rnd = Random() 
    let rec gen() = seq { yield rnd.Next(1,7) 
          yield! gen()  } 
    gen() 

> rollGen;; val rollGen : seq<int>

可以映射了。如果你想拉輸入值的靜態列表,你可以重用了創建D6

let d6Gen = rollGen |> Seq.map D6.Create 

> d6Gen;; val d6Gen : seq<D6>

無限隨機序列的隨機無限序列,你需要使用像

let rollList num = rollGen |> Seq.take num |> List.ofSeq 

let d6List num = d6Gen |> Seq.take num |> List.ofSeq ;; 

let _20rolls = rollList 20 ;;

> val _20rolls : int list = [3; 4; 2; 3; 5; 6; 4; 6; 6; 6; 5; 3; 4; 3; 2; 1; 2; 5; 3; 6]*)

let _30d6 = d6List 30 ;;

> val _30d6 : D6 list = [Two; Six; One; Three; Two; Three; One; One; Six; Six; Four; Four; Three; Four; One; Five; Three; Four; Four; Four; Three; Two; Six; Four; One; Three; One; Five; Two; Two]

Gist of just the code

+0

看起來非常有用,我會盡量在後面玩 – AlexC 2014-11-11 15:35:57