4

私は 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."
}

このドロー関数は 2 つのステップを持っているようには見えませんが、他にどのようにカードを何枚で​​も一番上に持っていき、それらのカードがない状態でリストを残すことができるか (またはすべきか) がわかりません。

(余談ですが、誰かがデッキ作成/シャッフルのためのより良い機能を持っているなら、私はすべて耳にします。これも少しハックに思えます...しかし、私の主な質問はリストの状態です)

4

4 に答える 4

2

私の意見では、次のいずれかのコードを書き直す必要があります。

(a)完全に不変の構造体、つまりNO varNO 可変コレクション

また

(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))
于 2013-09-30T04:07:38.423 に答える
2

デッキを「var」にするかどうかは別として、それtakedrop同時に行うことができます。splitAt

def draw(amount: Int): List[Card] = {
  val (ret, remainder) = deck.splitAt(amount)
  deck = remainder
  ret
}
于 2013-09-29T13:30:51.827 に答える
1

ちょっとした注意:メソッドの代わりにif.flattenを使用することを避けることができます。なぜあなたがその方法を「ハッキー」と考えるのかわかりませんが、私には完全に理にかなっているように見えます。for-syntax を使用したバリアントを次に示します。.flatMap.mapnewDeck

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
}
于 2013-09-29T14:37:14.927 に答える