枚举的可迭代数组

时间:2018-07-05 21:16:40

标签: swift enums protocols

我正在尝试初始化一副纸牌。我的卡片结构中有卡片属性。我的方法是尝试创建“枚举状态”数组,然后遍历所有这些以初始化每个卡。我这样做很麻烦。

游戏类

import Foundation

struct Set{
    var cards = [Card]()

    init(){
        let properties : [Any] = 
            [cardShape.self, cardColor.self, cardNumber.self, cardShading.self]
        for prop in properties{
        // Not really sure how to iterate through this array... 
        // Ideally it would be something like this.
        // Iterate through array, for property in array, 
        // card.add(property)
        }
    }
}

卡类

import UIKit
import Foundation

struct Card{
    var attributes : properties = properties()

    mutating func addProperty(value : Property){
        if value is cardShape{
            attributes.shape = value as! cardShape
        } else if value is cardColor{
            attributes.color = value as! cardColor
        } else if value is cardNumber{
            attributes.number = value as! cardNumber
        }else if value is cardShading{
            attributes.shading = value as! cardShading
        }else{
            print("error")
        }
    }
}

protocol Property{
    static var allValues : [Property] {get}
}

struct properties{
    var shape : cardShape = cardShape.none
    var color : cardColor = cardColor.none
    var number : cardNumber = cardNumber.none
    var shading : cardShading = cardShading.none
}

enum cardShape : String,Property{
    case Square = "■"
    case Triangle = "▲"
    case Circle = "●"
    case none
    static var allValues : [Property]{ return [cardShape.Square,cardShape.Triangle,cardShape.Circle]}
}

enum cardColor:Property  {
    case Red
    case Purple
    case Green
    case none

    static var allValues : [Property] {return [cardColor.Red,cardColor.Purple,cardColor.Green]}
}

enum cardNumber : Int,Property{
    case One = 1
    case Two = 2
    case Three = 3
    case none

    static var allValues : [Property] {return [cardNumber.One,cardNumber.Two,cardNumber.Three]}
}

enum cardShading: Property {
    case Solid
    case Striped
    case Outlined
    case none

    static var allValues : [Property] {return [cardShading.Solid,cardShading.Striped,cardShading.Outlined]}
}

总而言之,我的主要问题是尝试创建一个枚举数组,然后循环遍历枚举状态以初始化具有特定属性状态的卡。

1 个答案:

答案 0 :(得分:1)

您将要确保涵盖所有属性组合,并确保每张卡都具有四种属性中的一种。我建议使用嵌套循环:

for shape in cardShape.allValues {
    for color in cardColor.allValues {
        for number in cardNumber.allValues {
            for shading in cardShading.allValues {
                var card = Card()
                card.addProperty(shape)
                card.addProperty(color)
                card.addProperty(number)
                card.addProperty(shading)
                cards.append(card)
            }
        }
    }
}

我相信您的Card struct有点太复杂了。如果您更改自己的代表,则创建卡片会更加容易。

让您的卡将不同的属性表示为自己的属性:

struct Card {
    let shape: CardShape
    let color: CardColor
    let number: CardNumber
    let shading: CardShading
}

然后使用嵌套循环创建您的卡片:

for shape in CardShape.allValues {
    for color in CardColor.allValues {
        for number in CardNumber.allValues {
            for shading in CardShading.allValues {
                cards.append(Card(shape: shape, color: color, number: number, shading: shading))
            }
        }
    }
}

注释:

  • 您的枚举应以大写字母开头,而枚举值应以小写字母开头。
  • 为每个属性使用单独的属性将使检查卡之间的匹配属性变得更加容易。
  • 默认情况下,您将获得一个初始化所有属性的初始化程序。通过使用嵌套循环初始化它们,您将能够创建所有可能的卡。
  • 更改您的allValues属性以返回特定属性类型的数组(例如[CardShape])。

替代答案:

您可以使用MartinR's combinations函数来创建属性组合列表,而不是使用嵌套数组。将init添加到需要Card的{​​{1}}上,可以用两行代码创建卡片:

[Property]

工作原理:

  1. struct Card { var shape = CardShape.none var color = CardColor.none var number = CardNumber.none var shading = CardShading.none init(properties: [Property]) { for property in properties { switch property { case let shape as CardShape: self.shape = shape case let color as CardColor: self.color = color case let number as CardNumber: self.number = number case let shading as CardShading: self.shading = shading default: break } } } } // https://stackoverflow.com/a/45136672/1630618 func combinations<T>(options: [[T]]) -> AnySequence<[T]> { guard let lastOption = options.last else { return AnySequence(CollectionOfOne([])) } let headCombinations = combinations(options: Array(options.dropLast())) return AnySequence(headCombinations.lazy.flatMap { head in lastOption.lazy.map { head + [$0] } }) } struct SetGame { let cards: [Card] init(){ let properties: [Property.Type] = [CardShape.self, CardColor.self, CardNumber.self, CardShading.self] cards = combinations(options: properties.map { $0.allValues }).map(Card.init) } } properties.map { $0.allValues }数组的每个项目上调用allValues,用properties创建[[Property]]
  2. 这将传递给[[.square, .triangle, .circle], [.red, .purple, .green], [.one, .two, .three], [.solid, .striped, .outlined]],后者将创建一个具有以下所有81种组合属性的序列:combinations
  3. [[.square, .red, .one, .solid], ..., [.circle, .green, .three, .outlined]]按此顺序运行,以每种组合调用map,得到Card.init,其中有81张牌。