Haskell 哈斯克尔21点游戏

Haskell 哈斯克尔21点游戏,haskell,Haskell,嗨,我总结我的手有问题,因为A可以是1或11。我如何制作一个函数,用手(即[卡片]并计算总价值) 以下是我到目前为止的情况: handValue :: [Card]->[Int] handValue [] = 0 handValue (x:xs) = sum((val x)++([handValue xs])) 其中val已定义,并从卡返回一个值数组。例如val(“Ace”,“Hearts”)给出[1,11]val(“Five”,“Hearts”)给出[5] 任何指点都将不胜感激 编辑:

嗨,我总结我的手有问题,因为A可以是1或11。我如何制作一个函数,用手(即[卡片]并计算总价值)

以下是我到目前为止的情况:

handValue :: [Card]->[Int]
handValue [] = 0
handValue (x:xs) = sum((val x)++([handValue xs]))
其中val已定义,并从卡返回一个值数组。例如val(“Ace”,“Hearts”)给出[1,11]val(“Five”,“Hearts”)给出[5]

任何指点都将不胜感激

编辑:重复建议后,我有以下建议:

    handValue :: [Card]->[Int]
handValue [] = 0
handValue (x:xs) = 
            if (val x ==[1,11])
            then    (map sum (sequence [[1,11], handValue xs]))
                else [ sum [(val x)]++([handValue xs])]

除了修复你的功能之外,你还应该注意为什么它一开始就不起作用。首先,你给的类型是

handValue :: [Card] -> [Int]
但是递归定义有单个值,而不是列表,作为结果类型(第一个等式中的
0
文本;第二个等式中使用
sum
,即
Num a=>[a]->a

现在,假设类型更改为
[Card]->Int
,您的定义将是合法的,但结果会很奇怪。你的第二个等式是:

handValue (x:xs) = sum((val x)++([handValue xs]))
如果
x
是ace会发生什么
valx
将是
[1,11]
,因此这两个值将被串联并包含在总和中。实际上,你的A现在不是1或11,而是12分!n、 m的解决方案,我在这里解释为

Prelude> map sum . sequence $ [[1,11], [5], [6]]
[12,22]

通过为所有可能的ACE选择生成值列表(
序列
)并分别对所有可能的值进行求和(
映射和
),从而生成一个值列表(如您最初给出的签名中所示),从而绕过该问题。然而,这并不能完全解决问题,因为您最终需要决定其中一种可能性。现在我们可能有足够的材料来回答一个不同的问题,一旦你达到了这一点…

将a视为1还是11是一个机械的选择:将其视为11,除非这样做的总分超过21分。用户无需选择。瞧,我认为n.m.的解决方案是一个很好的方法(如果有人能解释它为什么有效的话)。我对纸牌游戏的无知已经显现出来了。。。在任何情况下,这意味着应该有一个自动决定来解释手的部分和,或者从n.m的解决方案中选择小于或等于21的最大和。@duplode我不知道如何在我的示例中使用它。我已经编辑了我的解决方案。为什么?它为什么有效?它为什么属于我们?为什么要发布答案而破坏了乐趣?@n.m.我理解使用序列,但我无法让它工作,请参见我的示例。@John
liftM sum。序列map val
应提供可能的手动值列表。
Prelude> map sum . sequence $ [[1,11], [5], [6]]
[12,22]