如何使用F#发行卡 [英] How to deal a card using F#
问题描述
我一直在使用F#对流行的纸牌游戏(情书)进行建模,以了解有关函数式编程的更多信息.
I've been working on modeling a popular card game (Love Letter) using F# to learn more about functional programming.
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)
我一直做得很好,直到我学会了如何建模如何绘制一张牌.为了测试这一点,我想从牌组中抽出所有卡片.我的程序如下所示:
I've been doing well until I got to how to model how to draw a card. To test this, I wanted to draw all the cards from the deck. My program would look something like this:
let deck = createDeck
while not deck.IsEmpty do
let card, newDeck = dealACard deck
// print the card
// how do I update the deck?
任何帮助或反馈都是很好的.
Any help or feedback would be great.
推荐答案
您可以使用List.sortBy
洗牌,然后在dealACard
方法中执行头尾模式匹配,以返回顶部的Option
卡和新卡组;如果卡组中没有更多卡,则None
.
You could shuffle the deck with a List.sortBy
and then perform a head tail pattern match in the dealACard
method to return an Option
of the top card and the new deck or None
if there are no more cards in the deck.
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 }
您还可以通过允许应用随机数生成函数来使shuffle
成为高阶函数
You could also make shuffle
a higher order function by allowing a random number generating function to be applied
let shuffle random deck =
deck |> List.sortBy (fun x -> random())
示例用法
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
每个评论的添加量
要以不变的方式跟踪卡座的当前状态,您可能需要某种可以接受卡座的递归函数
Addition per Comments
To keep track of the current state of the deck in an immutable way you would probably have some sort of recursive function that accepts a deck
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
这篇关于如何使用F#发行卡的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!