对于那些不知道什么是五张牌顺子的人:http://en.wikipedia.org/wiki/List_of_poker_hands#Straight
我正在Scala中编写一个小型的扑克模拟器来帮助我学习该语言,并且我创建了一个包含5张有序卡片的Hand类。每张卡都有等级和西服,均定义为枚举。 Hand类具有评估手位的方法,其中一种检查手是否包含顺子(我们暂时可以忽略顺子)。我知道有一些不错的算法可以确定Straight,但是我想看看我是否可以使用Scala的模式匹配来设计一些东西,所以我提出了以下内容:
def isStraight() = {
def matchesStraight(ranks: List[Rank.Value]): Boolean = ranks match {
case head :: Nil => true
case head :: tail if (Rank(head.id + 1) == tail.head) => matchesStraight(tail)
case _ => false
}
matchesStraight(cards.map(_.rank).toList)
}
那很好用,而且可读性很强,但是我想知道是否有任何方法可以消除这种情况。我想像像下面的东西,虽然我无法使其工作:
private def isStraight() = {
def matchesStraight(ranks: List[Rank.Value]): Boolean = ranks match {
case head :: Nil => true
case head :: next(head.id + 1) :: tail => matchesStraight(next :: tail)
case _ => false
}
matchesStraight(cards.map(_.rank).toList)
}
有任何想法吗?另外,作为附带的问题,对内部matchStraight定义的一般看法是什么?这应该是私有(private)的还是应该以其他方式进行?
最佳答案
您不能将信息传递给提取器,也不能使用来自另一个值的返回值中的信息,但if
语句除外-该语句可以解决所有这些情况。
您可以做的是创建自己的提取器来测试这些东西,但是如果没有任何重用,它不会给您带来太大的好处。
例如:
class SeqExtractor[A, B](f: A => B) {
def unapplySeq(s: Seq[A]): Option[Seq[A]] =
if (s map f sliding 2 forall { case Seq(a, b) => a == b } ) Some(s)
else None
}
val Straight = new SeqExtractor((_: Card).rank)
然后,您可以像这样使用它:
listOfCards match {
case Straight(cards) => true
case _ => false
}
但是,当然,您真正想要的只是
if
中的SeqExtractor
语句。因此,不要太爱解决方案,因为您可能会错过做事的简单方法。