我正在尝试学习scala,并决定创建一个扑克应用程序,让我的头围绕一些类对象。我的甲板工作正常,但我已经到了需要画5张牌的地步。到目前为止,我有:
import util.Random
case class Card(value: Int, color: String)
class Deck {
private var deck = newDeck
def draw(amount: Int): List[Card] = {
val ret = deck.take(amount)
deck = deck.drop(amount)
ret
}
def newDeck: List[Card] = {
Random.shuffle((1 to 13).map(x =>
List(Card(x, "D"), Card(x, "C"), Card(x, "H"), Card(x, "S"))).toList.flatten)
}
override def toString: String = "Deck has " + deck.length + " cards left."
}
这个绘图功能看起来似乎没有两个步骤 - 但是我不确定我是否可以(或者应该)拿到顶部多个卡片,并将列表保留在没有这些卡片的状态下?
(顺便说一句,如果某人有更好的甲板创建/洗牌功能,我会全神贯注,这看起来有点像hacky ......但我的主要问题是列表状态)
答案 0 :(得分:2)
撇开您是否希望将套牌设为“var”,您可以使用take
drop
和splitAt
def draw(amount: Int): List[Card] = {
val (ret, remainder) = deck.splitAt(amount)
deck = remainder
ret
}
答案 1 :(得分:2)
解决这个问题的最纯粹的功能方法已经为您编写了!其splitAt
,其模型绘制为获取一些卡并返回甲板的新状态。
此技术由集合api中的Queue.dequeue使用:
def dequeue: (A, Queue[A])
//Returns a tuple with the first element in the queue,
//and a new queue with this element removed.
所以draw
只是:
def draw[A](amount: Int): (A, Queue[A]) = deck.splitAt(amount)
答案 2 :(得分:2)
在我看来,你应该重写代码:
带完全不可变结构的(a),即 NO var ,无可变集合
或强>
(b)将某些可变集合替换为var deck: List[Card]
,例如ListBuffer
。
以下是(a)解决方案:
import util.Random
case class Card(value: Int, color: String)
class Deck(private val cards: Seq[Card]) {
def draw(amount: Int): (Deck, Seq[Card]) = {
val (ret, rem) = cards.splitAt(amount)
(new Deck(rem), ret)
}
override def toString: String = "Deck has " + cards.size + " cards left."
}
object Deck {
def apply(cards: Seq[Card] = Nil): Deck = cards match {
case Nil =>
val ncds = for(v <- 1 to 13; c <- Seq("D", "C", "H", "S")) yield Card(v, c)
new Deck(Random.shuffle(ncds))
case _ => new Deck(cards)
}
}
用例:
scala> :paste
// Entering paste mode (ctrl-D to finish)
//paste code here
// Exiting paste mode, now interpreting.
import util.Random
defined class Card
defined class Deck
defined object Deck
scala> val d1 = Deck()
d1: Deck = Deck has 52 cards left.
scala> val (d2, cards) = d1.draw(4)
d2: Deck = Deck has 48 cards left.
cards: Seq[Card] = Vector(Card(3,H), Card(2,S), Card(11,H), Card(8,C))
答案 3 :(得分:1)
只是一个小注意事项:如果您在.flatten
方法中使用.flatMap
而不是.map
,则可以避开newDeck
。我不知道为什么你认为这种方法“hacky”,它对我来说看起来非常合理。以下是使用for-syntax的变体:
def newDeck: List[Card] = {
val sorted = for {
value <- 1 to 13
color <- Seq("D", "C", "H", "S")
} yield Card(value, color)
Random.shuffle(sorted).toList
}