だから私は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()
_
threeOfSpades.createFullDeck()
の呼び出しは正しくないようです。これを行う別の方法があります。今回は、それまでに習得したであろうテクニックのみを使用します*。
最初に、前に定義したそれぞれの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
}
}
(*ツアーがその時点で配列に追加する方法を明示的に説明していなかったという注目すべき例外を除いて)
堅牢なコードの答えは、デッキを生成するときに列挙からの実際の値(つまり、.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()
関数をカード構造にコピーし、列挙型に値を追加してみてください。次の点に注意してください。
実験では、カードを作成する方法を求めています。そこで、メソッドを静的であると宣言して、インスタンスではなく構造体に作用するようにしました。
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()
お役に立てば幸いです。
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()
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()
は、考えられるすべてのトランプをループして、デッキに追加します。
上記の回答を読みましたが、クラスメソッドでない限りメソッドを使用できませんでした。そこで、追加した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、ランクの場合は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()
最初に、最も簡単な質問に取り組みます。完全なデッキを作成するコードをどこに配置するかはあなた次第ですが、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
}
}
_
上記のすべての例は本質的に命令型であり、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())
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
}
私は上記の人に同意します。この例では、この関数を呼び出すために最初にカードを初期化する必要があるため、クラスの方が理にかなっています...
驚いたことに、機能の実装をまだ誰も突き刺していません。ここに行きます:
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()
}
}
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()
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)")
}