Cam*_*ley 4 f# functional-programming
我一直致力于使用F#对流行的纸牌游戏(情书)进行建模,以了解有关函数式编程的更多信息.
module Game =
open Cards
open Players
type Deck = Card list
let dealACard (deck:Deck) =
let randomGenerator = System.Random()
let index = randomGenerator.Next deck.Length
let card = deck.Item index
(card, (deck |> List.filter((<>) card)))
let createPlayer playerNumber deck =
let card, newDeck = dealACard deck
({cards=[card]; playerNumber=playerNumber}, newDeck)
Run Code Online (Sandbox Code Playgroud)
我一直做得很好,直到我知道如何模拟如何绘制卡片.为了测试这个,我想从牌组中抽出所有牌.我的程序看起来像这样:
let deck = createDeck
while not deck.IsEmpty do
let card, newDeck = dealACard deck
// print the card
// how do I update the deck?
Run Code Online (Sandbox Code Playgroud)
任何帮助或反馈都会很棒.
F#列表是不可变的,所以如果deck.IsEmpty开始false,它将false永远存在.但是,没有理由让事情变得如此复杂.
假设您有一个已排序的牌组.我们只使用三张牌作为例子,但假设它是一个完整的牌组:
let deck =
[
{ Suit = Hearts; Face = Queen }
{ Suit = Diamonds; Face = King }
{ Suit = Spades; Face = Ace }
]
Run Code Online (Sandbox Code Playgroud)
您可以使用随机数生成器轻松地对卡座进行加扰:
let r = Random ()
let scrambledDeck = deck |> List.sortBy (fun _ -> r.Next ())
Run Code Online (Sandbox Code Playgroud)
第一次创建时scrambledDeck,它可能在FSI中看起来像这样:
> let scrambledDeck = deck |> List.sortBy (fun _ -> r.Next ());;
val scrambledDeck : Card list =
[{Suit = Spades;
Face = Ace;}; {Suit = Hearts;
Face = Queen;}; {Suit = Diamonds;
Face = King;}]
Run Code Online (Sandbox Code Playgroud)
但如果你再次这样做,它可能看起来像这样:
> let scrambledDeck = deck |> List.sortBy (fun _ -> r.Next ());;
val scrambledDeck : Card list =
[{Suit = Spades;
Face = Ace;}; {Suit = Diamonds;
Face = King;}; {Suit = Hearts;
Face = Queen;}]
Run Code Online (Sandbox Code Playgroud)
现在你有一个混乱的牌组,你可以简单地开始拉出牌,例如为了打印它们:
scrambledDeck |> List.iter (printfn "%O")
Run Code Online (Sandbox Code Playgroud)
您可以使用 a 洗牌List.sortBy,然后在方法中执行头尾模式匹配dealACard,以返回Option顶牌和新牌组的 an 或None如果牌组中没有更多牌。
type DealResult = {
Card : Card
Deck : Deck
}
let shuffle deck =
let random = new System.Random()
deck |> List.sortBy (fun x -> random.Next())
let dealACard deck =
match deck with
| [] -> None
| card::restOfDeck -> Some { Card = card; Deck = restOfDeck }
Run Code Online (Sandbox Code Playgroud)
您还可以shuffle通过允许应用随机数生成函数来创建更高阶的函数
let shuffle random deck =
deck |> List.sortBy (fun x -> random())
Run Code Online (Sandbox Code Playgroud)
用法示例
let deck = [{Rank = 1}; {Rank = 2}] |> shuffle
//val deck : Card list = [{Rank = 2;}; {Rank = 1;}]
let draw1 = deck |> dealACard
//val draw1 : DealResult option = Some {Card = {Rank = 2;};
// Deck = [{Rank = 1;}];}
let draw2 = match draw1 with
| Some d -> d.Deck |> dealACard
| None -> None
//val draw2 : DealResult option = Some {Card = {Rank = 1;};
// Deck = [];}
let draw3 = match draw2 with
| Some d -> d.Deck |> dealACard
| None -> None
//val draw3 : DealResult option = None
Run Code Online (Sandbox Code Playgroud)
为了以不可变的方式跟踪牌组的当前状态,您可能需要某种接受牌组的递归函数
type DealResult = {
Card : Card option
Deck : Deck
}
let dealACard deck =
match deck with
| [] -> { Card = None; Deck = deck }
| card::restOfDeck -> { Card = Some card; Deck = restOfDeck }
let rec dealAllCards deck =
let result = deck |> dealACard
match result.Card with
| None -> printfn "Cards out"
| Some c ->
printfn "%A" c
result.Deck |> dealAllCards
let deck = [(Two, Hearts); (Three, Hearts); (Four, Hearts)] |> shuffle
dealAllCards deck
//(Three, Hearts)
//(Four, Hearts)
//(Two, Hearts)
//Cards out
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
563 次 |
| 最近记录: |