web-dev-qa-db-ja.com

ランクとスーツの各組み合わせの1枚のカードで、カードの完全なデッキを作成するメソッドをカードに追加します

だから私はApple Swift Bookにある実験をしている。

これまでのところ、これを除いて、私はそれらすべてを行うことができました。以下は私が試したものですが、それを機能させる方法がわかりません。

Cardにメソッドを追加して、ランクとスーツの各組み合わせの1枚のカードでカードの完全なデッキを作成します。

_// Playground - noun: a place where people can play

enum Rank: Int {
    case Ace = 1
    case Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten
    case Jack, Queen, King

    func simpleDescription() -> String {
        switch self {
            case .Ace:
                return "ace"
            case .Jack:
                return "jack"
            case .Queen:
                return "queen"
            case .King:
                return "king"
            default:
                return String(self.toRaw())
        }
    }
}

enum Suit {
    case Spades, Hearts, Diamonds, Clubs

    func simpleDescription() -> String {
        switch self {
            case .Spades:
                return "spades"
            case .Hearts:
                return "hearts"
            case .Diamonds:
                return "diamonds"
            case .Clubs:
                return "clubs"
        }
    }
}

struct Card {
    var rank: Rank
    var suit: Suit

    func simpleDescription() -> String {
        return "The \(rank.simpleDescription()) of \(suit.simpleDescription())"
    }

    func createFullDeck() -> Array{
        var FullDeck: Array

        FullDeck = Card(rank: .Ace, suit: .Spades)
        FullDeck = Card(rank: .Two, suit: .Spades)

        return FullDeck
    }
}

let threeOfSpades = Card(rank: .Three, suit: .Spades)
let threeOfSpadesDescription = threeOfSpades.simpleDescription()

threeOfSpades.createFullDeck()
_
  • そのメソッド、配列に対して何を返す必要があるのか​​わかりませんか?
  • これを作成するためにforループを使用する必要がありますか?または列挙型でこれを行うための適切で簡単な方法はありますか
  • Card内にこのメソッドを作成するのはなぜですか?threeOfSpades.createFullDeck()の呼び出しは正しくないようです。
14
Arian Faurtosh

これを行う別の方法があります。今回は、それまでに習得したであろうテクニックのみを使用します*。

最初に、前に定義したそれぞれのRankおよびSuit列挙型を使用して、可能なランクとスーツを定義します。

次に、関数が各スーツ内の各ランクを反復処理し、それぞれにカードを作成し、最後にカードの配列を返します。

struct Card {
    var rank: Rank
    var suit: Suit
    func simpleDescription() -> String {
        return "The \(rank.simpleDescription()) of \(suit.simpleDescription())"
    }

    func createDeck() -> [Card] {
        let ranks = [Rank.ace, Rank.two, Rank.three, Rank.four, Rank.five, Rank.six, Rank.seven, Rank.eight, Rank.nine, Rank.ten, Rank.jack, Rank.queen, Rank.king]
        let suits = [Suit.spades, Suit.hearts, Suit.diamonds, Suit.clubs]
        var deck = [Card]()
        for suit in suits {
            for rank in ranks {
                deck.append(Card(rank: rank, suit: suit))
            }
        }
        return deck
    }
}

(*ツアーがその時点で配列に追加する方法を明示的に説明していなかったという注目すべき例外を除いて)

17
Jack James

堅牢なコードの答えは、デッキを生成するときに列挙からの実際の値(つまり、.Spades)を使用しません。たとえば、「ジョーカー」が後でランク列挙(列挙内の任意の場所)に追加された場合、デッキ生成関数変更なしで動作するはずです。

設計の質問(何を返すか、デッキの生成はカードの機能である必要がありますか?)は、このチュートリアルにはあま​​り関係ありませんが、深刻な機能がさらに構築される場合は、デッキクラスが望ましいと思われます。 (例:シャッフル)。したがって、今のところ、必要なのはCard構造体の関数から配列を返すことだけです。

次のコード(可能な限り、チュートリアルのこの時点までに説明されているもののみを使用)は、列挙値を知らなくてもスーツとランクの列挙をループし、配列を返すカード構造の関数を定義します。 :

static func deck() -> [Card] {
    var deck = [Card]()
    var suitCount = 1
    while let suit = Suit(rawValue: suitCount) {
        var rankCount = 1
        while let rank = Rank(rawValue: rankCount) {
            deck.append(Card(rank: rank, suit: suit))
            rankCount += 1
        }
        suitCount += 1
    }
    return deck
}

これを次のように呼び出します。

let deck = Card.deck()
var card3 = deck[3].simpleDescription()

関数をカード構造にコピーし、列挙型に値を追加してみてください。次の点に注意してください。

  • 列挙型に追加すると、ループが実行される回数がどのように変化するか
  • 両方の列挙型カウンターが1から始まること(列挙型で特に指定されていない場合、最初の生の値は1です)
  • 指定されていない配列インデックスは0から始まります(たとえば、deck [3]は実際にはスペードの4つです)
9
Alan O'Regan

実験では、カードを作成する方法を求めています。そこで、メソッドを静的であると宣言して、インスタンスではなく構造体に作用するようにしました。

struct Card {
    var rank: Rank
    var suit: Suit

    func simpleDescription() -> String {
        return "The \(rank.simpleDescription()) of \(suit.simpleDescription())"
    }

    static func deck() -> [Card] {
        var deck: [Card] = []
        for suit in [Suit.Spades, Suit.Hearts, Suit.Diamonds, Suit.Clubs] {
            for rank in 0...13 {
                if let unwrappedRank = Rank.fromRaw(rank) {
                    deck.append(Card(rank: unwrappedRank, suit: suit))
                }
            }
        }
        return deck
    }
}

それを利用するには:

let deck = Card.deck()

お役に立てば幸いです。

3
zeitgeist7

Swift Tour、Suit is String and Rank isInt。

struct Card {
    var rank: Rank
    var suit: Suit

    func simpleDescription () -> String{
        return "The \(rank.simpleDescription()) of \suit.simpleDescription())"
}

    func createDeck() -> [Card] {
        var n = 1
        var deck = [Card]()
        let suits = [Suit.spades, Suit.hearts, Suit.diamonds, Suit.clubs]
        while let rank = Rank(rawValue: n) {
            for suit in suits {
                deck.append(Card(rank: rank, suit: suit))
            }
            n += 1
        }
        return deck
    }
}   
let card = Card (rank: Rank.ace, suit: Suit.spades)
let deck = card.createDeck()
1
Sat

Forループがその方法です。ベースコードにいくつかの調整を加えました。まず、Suit列挙型にタイプを追加しました。

_enum Suit : Int
_

次に、カードのデッキを担当するDeckというクラスを追加しました。

_class Deck {
    var cards:Card[]

    init() {
        self.cards = Array<Card>()
    }

    func createDeck() {
        for suit in 0...Suit.Clubs.toRaw() {
            for rank in 1...Rank.King.toRaw() {
                self.cards += Card(rank: Rank.fromRaw(rank)!, suit: Suit.fromRaw(suit)!)
            }
        }
    }
}
_

func createDeck()は、考えられるすべてのトランプをループして、デッキに追加します。

1
Brian Tracy

上記の回答を読みましたが、クラスメソッドでない限りメソッドを使用できませんでした。そこで、追加した2つのメソッドの前に「静的」を追加しました。これが、私の提案です。

struct Card {
  var rank: Rank
  var suit: Suit

  func simpleDescription() -> String {
    return "The \(rank.simpleDescription()) of \(suit.simpleDescription())"
  }

  static func createDeck() -> Card[] {
    var deck = Card[]()
    for suit in [Suit.Spades, Suit.Clubs, Suit.Hearts, Suit.Diamonds] {
        for rankRawValue in 1...13 {
            let rank = Rank.fromRaw(rankRawValue)
            let card = Card(rank: rank!, suit: suit)
            deck += card
        }
    }
    return deck
  }

  static func printDeck(deck:Card[]) {
    for card in deck {
        println(card.simpleDescription())
    }
  }
}

let threeOfSpades = Card(rank: .Three, suit: .Spades)
let threeOfSpadesDescription = threeOfSpades.simpleDescription()

let deck = Card.createDeck()
Card.printDeck(deck)

しかし、私は同意します、「デッキ」クラスはより良いオプションでしょう...

0
Frédéric Adda

列挙型の定義の知識を避けようとしています...それは不器用なようです(私は初心者です)、それでも開始インデックスが必要です:スーツの場合は0、ランクの場合は1。

struct Card {
    var rank: Rank
    var suit: Suit
    func simpleDescription() -> String {
        return "The \(rank.simpleDescription()) of \(suit.simpleDescription())"
    }
    static func deck() -> [Card] {
        var deck = [Card]()
        var suitCount = 0
        while (Suit(rawValue: suitCount) != nil) {
            var rankCount = 1
            while (Rank(rawValue: rankCount) != nil) {
                deck.append(Card(rank: Rank(rawValue: rankCount)!, suit: Suit(rawValue: suitCount)!))
                rankCount++
            }
            suitCount++
        }
        return deck
    }
}
let deck = Card.deck()
0
Edward Flach

最初に、最も簡単な質問に取り組みます。完全なデッキを作成するコードをどこに配置するかはあなた次第ですが、Cardではなく、Deckクラスを作成し、 便利な初期化子 を提供してそこで実行します。

そうは言っても、それをCardクラスに追加する計画を続けましょう。残念ながら、列挙型のすべての可能な値を希望する方法でループする方法はありません(ただし、これについては間違っていると思います!)が、できます これを行う:

_let first_card = Rank.Ace.toRaw() // == 1
let last_card = Rank.King.toRaw() // == 13

for raw_rank in first_card...last_card {
    let rank = Rank.fromRaw(raw_rank)!
}
_

これを見ていきましょう。列挙型は、それぞれのケースに基になる値を割り当て、_case Ace = 1_と書くことで、1からカウントを開始するように設定します(デフォルトの0ではなく)。基になる値にアクセスするためにEnumによって提供されるAPIは、各EnumケースのtoRaw()メソッドです(Enum自体もRank.toRaw(Rank.Ace)の形式で提供します。

適切な名前のfromRaw()メソッドを使用して生の値から元に戻すことができます(したがって、Rank.fromRaw(1)はAceを提供します)が、注意点があります。オプションを返します。戻り値の型は_Rank?_、notRankです。値にアクセスするには、次のことを行う必要があります nilをチェックするか、強制的にアンラップします

Nilの確認:

_if let rank = Rank.fromRaw(1) {
    // Do stuff with rank, which is now a plain old Rank
}
else {
    // handle nil
}
_

強制アンラップ:

_var rank: Rank = Rank.fromRaw(1)!
_

ループについてのあなたの質問に答えるために:はい、それはそれを行う方法です= P、そして再びはい、それは設計上の決定ですが、配列についてです。 Deckクラスを作成し、代わりにそれを返すことも同様に理にかなっています。

拡張 を使用してメソッドを追加しましょう。拡張機能を使用すると、既存のタイプに機能を追加できます。クラス、列挙型、またはプリミティブ型に拡張機能を作成できます。ほとんど何でも。

_extension Card {

    func createFullDeck() -> Card[] {
        var deck: Array<Card> = []
        for raw_rank in Rank.Ace.toRaw()...Rank.King.toRaw() {
            deck += [
                Card(rank:Rank.fromRaw(raw_rank)!, suit:.Spades),
                Card(rank:Rank.fromRaw(raw_rank)!, suit:.Hearts),
                Card(rank:Rank.fromRaw(raw_rank)!, suit:.Diamonds),
                Card(rank:Rank.fromRaw(raw_rank)!, suit:.Clubs),
            ]
        }
        return deck
    }

}
_
0
Jiaaro

上記のすべての例は本質的に命令型であり、Swiftは関数型プログラミングを念頭に置いて構築されているため、問題を解決するためにより機能的なアプローチを採用しました。コードの完全なセットは次のとおりです。

私のランク列挙型(何らかの理由で列挙型のすべての値を反復処理することができないため、すべての値で配列を定義する必要があります)

enum Rank: Int, CustomStringConvertible {

    case ace = 1
    case two, three, four, five, six, seven, eight, nine, ten
    case jack, queen, king

    static let allRanks = [ace, two, three, four, five, six, seven, eight, nine, ten, jack, queen, king]

    var description: String {
        switch self {
        case .ace:
            return "ace"
        case .jack:
            return "jack"
        case .queen:
            return "queen"
        case .king:
            return "king"
        default:
            return String(self.rawValue)
        }
    }
}

スーツ列挙型(同様のタイプの配列を追加)

enum Suit: String, CustomStringConvertible  {

    case spades = "♠︎"
    case hearts = "♥︎"
    case diamonds = "♦︎"
    case clubs = "♣︎"

    static let allSuits = [spades, hearts, diamonds, clubs]

    var description: String {
        switch self {
        default:
            return rawValue
        }
    }

}

...そして最後にカード:

struct Card: CustomStringConvertible {
    var rank: Rank
    var suit: Suit

    var description: String {
        return "\(rank)\(suit)"
    }

    static func createDeckOfCards() -> [Card] {
        return Suit.allSuits.reduce([]) {
            deck, suit in deck + Rank.allRanks.reduce([]) {
                cardsInSuit, rank in cardsInSuit + [Card(rank: rank, suit: suit)]
            }
        }
    }
}

print(Card.createDeckOfCards())
0
austrum

IOS開発者として、私はこの本/チュートリアルを年に1回程度読むようにしています。今年は、初心者の開発者としてアプローチし、これまでにチュートリアルで提供された情報に基づいて何ができるかを考えました。 https://stackoverflow.com/users/262455/jack-james が指摘したように、彼らはまだ.appendを教えていない可能性があります。それを念頭に置いて、ここに私の答えがあります

func fullDeck() -> [String] {
    var deckOfCards = [String]()
    let suits = [Suit.clubs, Suit.diamonds, Suit.hearts, Suit.spades]
    let ranks = [Rank.ace, Rank.two, Rank.three, Rank.four, Rank.five, Rank.six, Rank.seven, Rank.eight, Rank.nine, Rank.ten ,Rank.jack, Rank.queen, Rank.king]
    for suit in suits {
        for rank in ranks {
            let card = Card(rank: rank, suit: suit)
            deckOfCards.append(card.simpleDescription())
        }
    }
    print(deckOfCards)
    return deckOfCards
}

私は上記の人に同意します。この例では、この関数を呼び出すために最初にカードを初期化する必要があるため、クラスの方が理にかなっています...

0
Reeder32

驚いたことに、機能の実装をまだ誰も突き刺していません。ここに行きます:

extension Array {
  func flatten<T>() -> T[] {
    let xs = (self as Any) as Array<Array<T>>
    return xs.reduce(T[]()) { (x, acc) in x + acc }
  }
}

extension Card {
  static func fullDeck() -> Card[] {
    let rawRanks = Array(Rank.Ace.toRaw()...Rank.King.toRaw())
    let suits: Suit[] = [.Spades, .Hearts, .Diamonds, .Clubs]
    return (rawRanks.map {
      rawRank in suits.map {
        suit in Card(rank: Rank.fromRaw(rawRank)!, suit: suit)
        }
      }).flatten()
  }
}
0
Manav

Swift 3:のソリューション全体は次のとおりです。

struct Card {

    var rank: Rank
    var suit: Suit

    func simpleDescription() -> String {
        return "The \(rank.simpleDescription()) of \(suit.simpleDescription())"
    }
    func createDeck() -> [Card] {
        let suits = [Suit.spades, Suit.hearts, Suit.clubs, Suit.diamonds]
        var deck = [Card]()

        for theSuit in suits {
            for theRank in Rank.Ace.rawValue...Rank.King.rawValue {
                deck.append(Card(rank: Rank(rawValue: theRank)!, suit: theSuit))
            }
        }
        return deck
    }
}

あなたはそれをこのように呼ぶことができます:

let aceOfHearts = Card(rank: .Ace, suit: .hearts)
let deck = aceOfHearts.createDeck()
0
mrabins

Swiftも学び始めたばかりで、これと同じ問題がありました。カード構造内にカードの完全なデッキを作成するメソッドを作成するという実験はかなり奇妙だと思いました。

これらの回答を見て、公式のApple "The Swift Programming Language(Swift 2.1)"ツアーを読んだ後、次のように解決しました。

struct Card {
    var rank: Rank
    var suit: Suit

    func simpleDescription() -> String {
        return "The \(rank.simpleDescription()) of \(suit.simpleDescription())"
    }

    func createDeck() -> [Card] {
        let suits = [Suit.Spades, Suit.Hearts, Suit.Clubs, Suit.Diamonds]
        var deck = [Card]()

        for theSuit in suits {
            for theRank in Rank.Ace.rawValue...Rank.King.rawValue {
                deck.append(Card(rank: Rank(rawValue: theRank)!, suit: theSuit))
            }
        }

        return deck
    }
}

let aceOfHearts = Card(rank: .Ace, suit: .Hearts)
let deck = aceOfHearts.createDeck()

for card in deck {
    print("\(card.rank) of \(card.suit)")
}
0