简体   繁体   English

F#造型扑克牌

[英]F# modeling playing cards

I am trying to represent standard playing cards in F#. 我想在F#中代表标准扑克牌 My goal is to implement a clone of Microsoft Solitaire (the one that comes with Windows) , a game in which Cards' Suit, Face, and Color are important. 我的目标是实现Microsoft Solitaire (Windows附带的那个)的克隆,这是一种卡片套装,面部和颜色很重要的游戏。 This exercise is mostly intended as a way to learn some F#. 这个练习主要是为了学习一些F#。

I have considered using discriminated unions: 我考虑过使用歧视的工会:

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

with a record type for Card: 卡的记录类型:

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

However, a Card's Color can be inferred from its Suit—all Diamonds and Hearts are Red, and all Clubs and Spades are Black. 但是,卡片的颜色可以从它的套装中推断出来 - 所有钻石和红心都是红色的,所有的俱乐部和黑桃都是黑色的。 Suit cannot be determined from Color alone. 不能仅从Color确定套装。 Perhaps something like this is appropriate: 也许这样的事情是合适的:

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;
}

But this doesn't seem right, since this allows incorrect combinations, eg Black Hearts and Red Spades. 但这似乎不对,因为这允许不正确的组合,例如Black Hearts和Red Spades。

My questions are: 我的问题是:

  1. What is the most idiomatic way to handle Suit and Color, considering that Color is dependent on Suit? 考虑到Color依赖于Suit,最适合处理套装和颜色的方法是什么?
  2. Should the concept of Color even be explicitly represented? Color的概念是否应该明确表示? One could theoretically just replace all occurrences of Color with pattern matches against Diamonds or Hearts (which are red) and Clubs or Spades (which are black). 理论上,人们可以将所有出现的颜色替换为与钻石或心形(红色)和俱乐部或黑桃(黑色)的模式匹配。

Since Color can always be inferred from Suit , there's no reason to model it explicitly; 由于Color总是可以从Suit推断出来,所以没有理由对它进行明确的建模; you'll want to make illegal states unrepresentable . 你想让非法国家无法代表

You can still get a nice programming experience out of your model, and have a nice way of modelling colour, using an Active Pattern : 您仍然可以从模型中获得良好的编程体验,并使用活动模式有一种很好的颜色建模方法:

type Suit =
    | Diamonds
    | Hearts
    | Clubs
    | Spades

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

This would enable you to pattern match on Suit , like this inane example: 这将使您能够在Suit上进行模式匹配,就像这个愚蠢的例子:

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

Usage example from FSI: FSI的用法示例:

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

You can add a recording method: 您可以添加录制方法:

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

Example: 例:

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

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

Red Black Для продолжения нажмите любую клавишу . RedBlackДляпродолжениянажмителюбуюклавишу。 . .

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM