所以我试图用F#为学校项目创建一个纸牌游戏。我来自C#并且在理解F#中的内容方面存在问题。我有类型
Player = {Name : String; Hand : Card list}
代表玩家
removeat[i]
的内容。
答案 0 :(得分:6)
let returnFirstElement list =
match list with
| h::t -> Some(h),t
| [] -> None,[]
将你的列表传递给它,它将返回一个元组。第一个值将是您的卡,第二个值是卡的其余部分。
使用Some和None就好像你的牌组中没有卡牌那么你就不会得到一张牌。
由于您来自C#背景,因此将Some
视为可空类型,将None
视为null。如果您不确定使用它们是非常常见的,请查看F#Some
和None
。
你可以像
一样使用它 let (topCard, restOfDeck) = returnFirstElement deckOfCards
如果需要可以给你更多帮助,但这应该是一个足够好的开始。
答案 1 :(得分:2)
要在F#中编写惯用的功能代码,您需要考虑如何明确地模拟系统的状态。每个玩家都有一手牌代表国家的一部分,但我们也需要模拟牌组的状态。
从逻辑上讲,从牌组中抽出会影响牌手和牌组本身。
当牌组中没有牌时,我们还需要考虑错误情况。
这是一个简单的例子,当卡片中没有卡片时,只会出现错误。
type Player = {Name : string; Hand : Card list}
let draw player deck =
match deck with
|[] -> invalidArg "deck" "No cards in deck!"
|drawn::rest -> ({ player with Hand = drawn :: player.Hand }, rest)
您向绘制功能提供了一个Player
和一个由Card list
表示的套牌,它会返回一个新的Player
,其中有一张从牌组中取出的牌和一张新{{1}没有绘制的卡片。
对于某些游戏,你可能最好有两张牌,一张牌,一张牌,一张牌。然后,当你用完卡片时,你可以通过改组丢弃牌来创建一个新牌组。
答案 2 :(得分:-1)
你当然可以在F#中使用任何.Net。这不是惯用的F#,但话说再次,它的递归是多少。基本上,如果要从F#列表中删除元素,可能F#列表不是要使用的最佳集合。您当然可以随时向其filter
申请。但如果您的所有商品都是唯一的,请考虑使用套装。
这是一个带有.RemoveAt的版本:
open System.Collections.Generic
let xs = ResizeArray [1;2;3]
xs.RemoveAt(2)
xs
ResizeArray是C#List的同义词。
关于只是移动第一张牌并休息,你可以使用' tail'并且' head'功能。