【问题标题】:F# modeling playing cardsF#建模扑克牌
【发布时间】:2015-03-12 13:44:22
【问题描述】:

我试图在 F# 中表示 standard playing cards。我的目标是实现Microsoft Solitaire(Windows 附带的那个)的克隆,这是一款卡片的套装、面部和颜色都很重要的游戏。这个练习主要是为了学习一些 F#。

我考虑过使用有区别的联合:

type Suit =
    | Diamonds
    | Hearts
    | Clubs
    | Spades

type Color =
    | Red
    | Black

type Face =
    Two | Three | Four | Five | Six | Seven |
    Eight | Nine | Ten | Jack | Queen | King | Ace

卡的记录类型:

type Card = {
    suit: Suit;
    face: Face;
    color: Color;
}

然而,一张牌的颜色可以从它的花色中推断出来——所有的方块和红桃都是红色的,所有的梅花和黑桃都是黑色的。花色不能仅从颜色来确定。也许这样的事情是合适的:

type Suit =
    | Diamonds of Color //should always be red
    | Hearts of Color //should always be red
    | Clubs of Color //should always be black
    | Spades of Color //should always be black

type Face =
    Two | Three | Four | Five | Six | Seven |
    Eight | Nine | Ten | Jack | Queen | King | Ace

type Card = {
    suit: Suit;
    face: Face;
}

但这似乎不正确,因为这允许不正确的组合,例如黑心和红黑桃。

我的问题是:

  1. 考虑到 Color 依赖于 Suit,处理 Suit 和 Color 最惯用的方法是什么?
  2. 是否应该明确表示颜色的概念?理论上,可以将所有出现的颜色替换为与菱形或红心(红色)和梅花或黑桃(黑色)匹配的图案。

【问题讨论】:

    标签: f# playing-cards


    【解决方案1】:

    由于Color 总是可以从Suit 推断出来,因此没有理由对其进行显式建模;你会想要illegal states unrepresentable

    使用Active Pattern,您仍然可以从您的模型中获得良好的编程体验,并有一种很好的颜色建模方式:

    type Suit =
        | Diamonds
        | Hearts
        | Clubs
        | Spades
    
    let (|Red|Black|) suit =
        match suit with
        | Diamonds | Hearts -> Red
        | Clubs | Spades -> Black
    

    这将使您能够在 Suit 上进行模式匹配,就像这个愚蠢的例子:

    let printColor card =
        match card.Suit with
        | Red -> "Red"
        | Black -> "Black"
    

    来自 FSI 的使用示例:

    > printColor { Suit = Spades; Face = Ace };;
    val it : string = "Black"
    > printColor { Suit = Diamonds; Face = King };;
    val it : string = "Red"
    

    【讨论】:

    • 主动模式是如此的酷和有用:) 每次我看到它们的一个很酷的应用程序时,我都会惊叹于如此简单的机制如何在清理代码方面如此有用。
    【解决方案2】:

    可以添加录制方式:

    type Card = 
        {suit: Suit;face: Face}
        member this.Color = 
            match this.suit with
                | Diamonds | Hearts -> Red
                | Clubs | Spades -> Black
    

    例子:

    let v = {suit = Diamonds;face = Two}
    printfn "%A" v.Color
    
    let v1 = {suit = Clubs;face = Two}
    printfn "%A" v1.Color
    

    红色 黑色的 Для продолжения нажмите любую клавишу 。 . .

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-19
      • 2011-07-09
      相关资源
      最近更新 更多