如何使用F#发行卡 [英] How to deal a card using F#

查看:92
本文介绍了如何使用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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆