代码之家  ›  专栏  ›  技术社区  ›  GeraltDieSocke

如何比较数组中的3个值与“not”或“all”相等?

  •  -2
  • GeraltDieSocke  · 技术社区  · 8 年前

    问题:

    我在做游戏 Set 因此,我必须在棋盘上选择3张牌。 每个卡上都有四个不同的属性:

    • 颜色(数字介于0和2之间)
    • 形状(数字介于0和2之间)
    • 阴影(数字介于0和2之间)
    • 数字(0到2之间的数字)

    现在我要比较3张选中的牌,并计算它们是否匹配。我不能只凭脑子去想这个问题,因为我还想用一种好的方式来写,而不是用几十个for循环。

    因此,如果:

    • 每张卡上的4个属性都相等
      • 卡1有红色、三角形、2、条纹,卡2+3也有红色、三角形、2、条纹
    • 每张卡上有4种不同的属性
      • 如果卡1有红色,三角形,2,条纹,没有其他卡可以有这些

    指派

    所以现在我应该发明一个解决方案,“根据老师”是非常简单的,我的应用程序模型不应该超过100行代码。现在我有将近100行代码,我需要做更多的事情。所以我应该以一种非常干燥的方式来实现这一点。

    你如何解决这个问题

    我需要一些指导来引导我走向正确的方向。 Swift中是否有我缺少的数组内置方法,或者需要实现某种协议?

    3 回复  |  直到 8 年前
        1
  •  3
  •   Martin R    8 年前

    ( 备注: 以下解决方案针对 集合游戏,三个值都是0、1或2。不会有帮助的 检查是否有三个 任意的 值都相等或都不同。)

    一点数学知识有帮助。如果有三个整数x,y,z在范围内 0到2,那么x+y+z是3的倍数if(并且仅当)

    • x,y,z都相等,或者
    • x,y,z都是不同的。

    这个可以查一下

    if (x + y + z) % 3 == 0 {
        // x, y, z are all equal or all different.
    }
    

    因此,如果 Card 类型定义为

    struct Card {
        let number: Int // 0, 1, 2
        let symbol: Int // 0, 1, 2
        let shade:  Int // 0, 1, 2
        let color:  Int // 0, 1, 2
    }
    

    然后,对有效集的检查可以非常有效地完成:

    func isValidMatch(c1: Card, c2: Card, c3: Card) -> Bool {
        return (c1.number + c2.number + c3.number) % 3 == 0
            && (c1.symbol + c2.symbol + c3.symbol) % 3 == 0
            && (c1.shade + c2.shade + c3.shade) % 3 == 0
            && (c1.color + c2.color + c3.color) % 3 == 0
    }
    

    或者,为各种属性定义原始值在0、1、2范围内的枚举:

    struct Card {
    
        enum Number: Int {
            case one, two, three
        }
    
        enum Symbol: Int {
            case diamond, squiggle, oval
        }
    
        enum Shade: Int {
            case solid, striped, open
        }
    
        enum Color: Int {
            case red, green, purple
        }
    
        let number: Number
        let symbol: Symbol
        let shade: Shade
        let color: Color
    }
    
    
    func isValidMatch(c1: Card, c2: Card, c3: Card) -> Bool {
        return (c1.number.rawValue + c2.number.rawValue + c3.number.rawValue) % 3 == 0
            && (c1.symbol.rawValue + c2.symbol.rawValue + c3.symbol.rawValue) % 3 == 0
            && (c1.shade.rawValue + c2.shade.rawValue + c3.shade.rawValue) % 3 == 0
            && (c1.color.rawValue + c2.color.rawValue + c3.color.rawValue) % 3 == 0
    }
    
        2
  •  0
  •   ielyamani    8 年前

    你的 Card 类应符合 Equatable 协议:

    class Card : Equatable {
        let color: Int
        let shape: Int
        let shade: Int
        let number: Int
    
        //This is a failable initializer (https://developer.apple.com/swift/blog/?id=17) since we haven't used enums like in another answer, which are safer. 
        init?(color: Int, shape: Int, shade: Int, number: Int) {
            //make sure that all properties are between 0 and 2
            guard 0...2 ~= color, 0...2 ~= shape, 0...2 ~= shade, 0...2 ~= number else {
                fatalError("All properties should be integers between 0 and 2")
            }
            self.color = color
            self.shape = shape
            self.shade = shade
            self.number = number
        }
    
        static func == (lhs: Card, rhs: Card) -> Bool {
            return lhs.color == rhs.color && lhs.shape == rhs.shape && lhs.shade == rhs.shade && lhs.number == rhs.number
        }
    }
    

    所以当所有四个属性都相等时,就有了相等。如所指出的 @ MartinR :在Swift 4.1及以上版本中,编译器将合成 == 操作员自动地,并且足以声明符合等价协议。

    为了符合等价协议,您所要做的就是实现这个功能:

    static func == (lhs: Card, rhs: Card) -> Bool
    

    现在,如果要检查三张牌是否相等,请使用 = 操作员:

    let c1 = Card(color: 2, shape: 1, shade: 0, number: 1)
    let c2 = Card(color: 2, shape: 1, shade: 0, number: 1)
    let c3 = Card(color: 2, shape: 1, shade: 0, number: 1)
    let c4 = Card(color: 2, shape: 1, shade: 0, number: 2)
    
    (c1 == c2) && (c2 == c3)
    

    最后,如果您想要一个函数一次比较三张卡,可以将此代码添加到 班级:

    class func compareThreeCards(firstCard: Card, secondCard: Card, thirdCard: Card) -> Bool {
        return (firstCard == secondCard) && (secondCard == thirdCard)
    }
    

    你可以这样使用它:

    Card.compareThreeCards(firstCard: c1!, secondCard: c2!, thirdCard: c3!)
    
        3
  •  0
  •   Michel Koga    8 年前

    自Swift4.1以来,结构和枚举可以免费拥有相等的和可哈希的(不适用于类)。

    例如,如果您有一个卡片结构,只需使这个类型是可哈希的,用您的卡片创建一个集合,然后比较它们。

    struct Card: Hashable {
    
        var color: Int
        var shape: Int
        var shade: Int
        var number: Int
    }
    
    let card1 = Card(color: 2, shape: 2, shade: 2, number: 0)
    let card2 = Card(color: 2, shape: 2, shade: 2, number: 1)
    let card3 = Card(color: 3, shape: 1, shade: 0, number: 2)
    
    
    print(card1 == card2 && card2 == card3) // Prints false, all different.
    
    let card4 = Card(color: 1, shape: 2, shade: 0, number: 0)
    let card5 = Card(color: 1, shape: 2, shade: 0, number: 0)
    let card6 = Card(color: 1, shape: 2, shade: 0, number: 0)
    
    print(card4 == card5 && card5 == card6) // Prints true, all the same.
    

    注(感谢利奥·达布斯):布景是一个无序的收藏。