使用Enums初始化卡片组

时间:2019-02-24 16:07:43

标签: ios swift

我正在尝试为游戏Sets初始化一副纸牌,每张纸牌有4个参数:颜色,形状,阴影和纸牌上的形状数量。

我的卡类如下:

enum CardColor : Int {
    case red = 1
    case purple = 2
    case green = 3
}

enum CardShape : Int {
    case line = 1
    case snake = 2
    case diamond = 3
}

enum CardShade : Int {
    case empty = 1
    case filled = 2
    case stripes = 3
}

class Card {

    var color : CardColor
    var shape : CardShape
    var shade : CardShade
    var number : Int
    var image : String

    var isTapped = false
    var isMatched = false


    init(color : CardColor , shape : CardShape, shade : CardShade , number : Int) {
        self.color = color
        self.shape = shape
        self.shade = shade
        self.number = number

        self.image = "\(color.rawValue)\(shape.rawValue)\(shade.rawValue)\(number)"

    }
}

我找不到初始化卡座的方法,我目前正在使用手动制作的Card卡数组:

cards = [Card(color: .red, shape: .diamond, shade: .filled, number: 1)... 

以此类推。

卡片看起来像这样:

enter image description here

2 个答案:

答案 0 :(得分:2)

For循环在这里可以很好地工作。使用4个嵌套循环来遍历属性并在内部循环内创建新卡:

在您的枚举中添加CaseIterable,以便轻松访问所有案例:

enum CardColor : Int, CaseIterable {
    case red = 1
    case purple = 2
    case green = 3
}

然后:

// Array to hold the cards
var cards = [Card]()

for color in CardColor.allCases {
    for shape in CardShape.allCases {
        for shade in CardShade.allCases {
            for number in 1...3 {
                // Create a new card and append it to the array
                cards.append(Card(color: color, shape: shape, shade: shade, number: number))
            }
        }
    }
}

答案 1 :(得分:1)

我将使用一系列flatMaps来生成完整的牌组。我还要更改其他一些内容:

  • 使Card为结构。任何一条为红色的空行的卡片都与其他任何一条为红色的空行的卡片相同。即卡片的身份与价值没有分别,因此引用类型(类)将无用。
  • isTapped结构中提取isMatchedCard字段。那里没有意义。如果您向Set玩家提供一张牌并询问他们isTapped的值是什么,他们将一无所知。它根本不属于。我会制作类似CardSlotCardView这样的东西来跟踪此类UI状态。
  • image更改为imageName。如果它确实是image,则希望它具有类型UIImageNSImage,而不是String
    • imageName更改为计算属性。现在,所有存储的字段(colorshapeshadeparity)都可以由成员明智的初始化程序填充,编译器将自动为该结构合成。
  • 将枚举更改为嵌套类型Card,以防止其所有名称中使用不必要的Card前缀。
  • 为名片图像使用更多易读的名称。相信我,这将是很大的帮助。找到green_line_filled_three.png胜过3123.png
    • 现在不需要rawValue来生成图像名称,可以将其删除。几乎不再需要使用Int原始值。 C interop是我唯一能想到的。要生成所有枚举值,可以使用CaseIterable,而不是在init(rawValue: Int)范围内映射Int
  • number: Int更改为arity: Card.arity,以防止出现非法值

这是下面的样子:

struct Card {
    enum Color: CaseIterable { case red, purple, green }
    enum Shape: CaseIterable { case line, snake, diamond }
    enum Shade: CaseIterable { case empty, filled, striped }
    enum Arity: CaseIterable { case one, two, three }

    let color: Color
    let shape: Shape
    let shade: Shade
    let arity: Arity

    var imageName: String {
        return "\(color)\(shape)\(shade)\(arity)"
    }

    static func generateFullDeck() -> [Card] {
        return Color.allCases.flatMap { color in
            return Shape.allCases.flatMap { shape in
                return Shade.allCases.flatMap { shade in
                    return Arity.allCases.map { arity in
                        return Card(color: color, shape: shape, shade: shade, arity: arity)
                    }
                }
            }
        }
        /* 
        // Alternate implementation which prevents the "pyramid of doom" nesting,
        // But it's considerably more complex
        return Color.allCases.lazy.flatMap { color in
            Shape.allCases.map { shape in (color, shape)}
        }.flatMap { (color, shape) in
            Shade.allCases.map { shade in (color, shape, shade) }
        }.flatMap { (color, shape, shade) in
            Arity.allCases.map { arity in

            }
        })      
        */
    }
}


Card.generateFullDeck().forEach { print($0) }