对于那些不知道什么是五张牌顺子的人: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语句。因此,不要太爱解决方案,因为您可能会错过做事的简单方法。

10-07 13:36