我想在Haskell中的游戏中返回一系列卡片。例如:
[(SIX,D),(SEVEN,D),(EIGHT,S)] ~> [(SIX,D),(SEVEN,D)]
[(SIX,D),(SEVEN,S)] ~> []
[(SIX,D),(SEVEN,D)] ~> [(SIX,D),(SEVEN,D)]
到目前为止,我有这个功能:
findSeq :: [Card] -> [Card]
findSeq [] = []
findSeq (h:t)
| null t = [h]
| Just h == (pCard (head t) pack) = h:findSeq t
| otherwise = [h]
它甚至返回第一张卡:即,不适合上面的示例2。如果没有连续元素的序列,我怎么能返回序列,或者什么都不返回?
我也试着过滤它们,但我收到了"太多的参数异常"。有什么帮助吗?
我会这样做:
import Data.List (groupBy)
import Data.Function (on)
data Suit = Clubs | Diamonds | Hearts | Spades deriving Eq
data Face = Ace | Two | Three | Four | Five | Six | Seven | Eight | Nine | Ten
| Jack | Queen | King deriving Enum
type Card = (Face, Suit)
findSequences :: [Card] -> [[Card]]
findSequences = [sequence | sequence <- groupBy ((==) `on` snd),
contiguous (map fst sequence),
length sequence > 1]
contiguous :: Enum a => [a] -> Bool
contiguous (x:xs) = map fromEnum xs == take (length xs) [fromEnum x + 1 ..]
findSequences
函数查找牌组中的所有序列(单卡序列除外)。
从数学上讲,将一张牌视为一张牌的序列实际上是完全合理的。因此,不改变这种行为是个好主意。。。只需扩展定义,就可以从中获得真正想要的结果。
真正的问题不是你把单个卡片作为单个元素序列,而是你没有得到它们背后的任何东西。要解决此问题,您不仅需要首先获得列表中的第一个序列,还需要所有序列:
findSeqs :: [Card] -> [[Card]]
findSeqs [] = []
findSeqs [h] = [[h]]
findSeqs (h:t@(h':_)) -- avoid `head` and `null`... pattern matching FTW!
| Just h == (pCard h' pack) = h ^: findSeqs t
| otherwise = [h] : findSeqs t
我使用了辅助
(^:) :: a -> [[a]] -> [[a]]
h ^: (hl:ls) = (h:hl) : ls
_ ^: [] = []
一旦你有了findSeqs
,你只需要浏览第一个非退化序列的结果。