我正在使用 F# 创建一个小纸牌游戏,但由于循环类型依赖性,我遇到了一些问题。我有以下卡片类型(简化):
type Monster =
{ Health: int
Attack: int
SkillText: string option }
type Spell =
{ EffectText: string }
type Kind =
| Monster of Monster
| Spell of Spell
type Card =
{ Name: string
Image: string
Kind: Kind
IsPlayer: bool
CanPlay: Board -> bool }
这个想法是,在创建新卡牌时,必须根据当前棋盘状态定义其发挥所需的条件。
板型为
and Board =
{ PlayerHand: Hand
EnemyHand: Hand
PlayerDeck: Deck
EnemyDeck: Deck
PlayerField: Field
EnemyField: Field
PlayerGraveyard: Graveyard
EnemyGraveyard: Graveyard }
我的问题是,Board内部的类型都依赖于
Card
类型,所以我需要在Card类型之后定义它,但是Card类型取决于Board类型。我知道我可以使用泛型来撤销循环依赖,但我有以下问题:
如果我定义一个
Board<'Card>
类型,我需要将 Board 引用的所有类型设置为通用类型。这不仅对我来说显得很冗长,而且对我的应用程序也没有多大意义。我永远不会做任何不是牌的东西。我知道我可以改为 Card<'Board>
,但这似乎不太直观,而且我在 Board<'Card>
中遇到的问题同样适用。
有没有什么方法可以在不使用泛型的情况下解决这个问题,同时保持纯粹的功能(除了对依赖于
and
的每种类型使用 Card
关键字)?
是的!有很多方法可以解决这个问题
and
关键字我看到你已经在
and Board = ...
中使用过它,所以我假设你知道它,但你不想使用它。以防万一:
type Card =
{ Name: string
Image: string
Kind: Kind
IsPlayer: bool
CanPlay: Board -> bool }
and Board =
{ PlayerHand: Hand
EnemyHand: Hand
PlayerDeck: Deck
EnemyDeck: Deck
PlayerField: Field
EnemyField: Field
PlayerGraveyard: Graveyard
EnemyGraveyard: Graveyard }
这允许您一起编写循环类型,但它们必须位于同一个文件中。
这取决于您想要的游戏,但也许 CanPlay 不需要依赖于棋盘?通常这样的事情可以是一个简单的枚举:
type PlayCondition =
| BoardIsEmpty
| ManaIsAbove of int
type Card =
{ Name: string
Image: string
Kind: Kind
IsPlayer: bool
CanPlay: PlayCondition }
使用您想要在板上使用的功能定义您的界面:
type IBoard =
abstract member GetCardAt: x: int -> y: int -> Card
and Card =
{ Name: string
Image: string
Kind: Kind
IsPlayer: bool
CanPlay: IBoard -> bool }
在船上实施:
type Board =
{ PlayerHand: Hand
EnemyHand: Hand
PlayerDeck: Deck
EnemyDeck: Deck
PlayerField: Field
EnemyField: Field
PlayerGraveyard: Graveyard
EnemyGraveyard: Graveyard }
interface IBoard with
member this.GetCardAt x y = ...
希望这有帮助!