Arrays 如何将一个数组中的3个值与“1”进行比较;不是";或;“全部”;彼此平等?

Arrays 如何将一个数组中的3个值与“1”进行比较;不是";或;“全部”;彼此平等?,arrays,swift,Arrays,Swift,问题: 我正在构建游戏,因此我必须在棋盘上选择3张牌。 每个卡上都有四种不同的属性: 颜色(0和2之间的数字) 形状(数字介于0和2之间) 阴影(介于0和2之间的数字) 数字(介于0和2之间的数字) 现在我想比较3张选择的卡片,计算它们是否匹配。我不能只想着这个,因为我也想用一种好的方式写它,而不是用几十个for循环 因此,如果: 每张卡上的所有4个属性都相等 卡1有红色三角形2条纹,卡2+3也有红色三角形2条纹 4每张卡上的属性都不同 如果卡1有红色三角形条纹,卡2有条纹,则其他卡

问题:

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

  • 颜色(0和2之间的数字)
  • 形状(数字介于0和2之间)
  • 阴影(介于0和2之间的数字)
  • 数字(介于0和2之间的数字)
现在我想比较3张选择的卡片,计算它们是否匹配。我不能只想着这个,因为我也想用一种好的方式写它,而不是用几十个for循环

因此,如果:

  • 每张卡上的所有4个属性都相等
    • 卡1有红色三角形2条纹,卡2+3也有红色三角形2条纹
  • 4每张卡上的属性都不同
    • 如果卡1有红色三角形条纹,卡2有条纹,则其他卡不能有其中一张
作业

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

您将如何解决这个问题

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

您的
类应符合协议:

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及更高版本中,编译器将自动合成
==
运算符,并足以声明符合Equalable协议

要符合Equalable协议,您只需实现以下功能:

static func == (lhs: Card, rhs: Card) -> Bool
现在,如果要检查3张卡是否相等,请使用
=
运算符:

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!)
(备注:以下解决方案是针对 设置游戏,其中所有三个值都是0、1或2。这没有帮助 检查三个任意值是否都相等或不同。)

一点数学知识会有帮助。如果有三个整数x,y,z在 0到2,则x+y+z是3的倍数如果(且仅当)

  • x、 y,z都相等,或者
  • x、 y,z都不一样
这可以通过以下方式进行检查:

if (x + y + z) % 3 == 0 {
    // x, y, z are all equal or all different.
}
因此,如果
类型定义为

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
}

自Swift 4.1以来,结构和枚举可以免费使用equalable和Hashable(不适用于类)

例如,如果您有一个Card结构,只需将此类型设置为可哈希的,用您的卡创建一个集合,然后比较它们

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.

注意(感谢Leo Dabus):设置为无序集合。

您可以添加定义类卡的代码吗?你到目前为止试过的代码会让你的问题更清楚。颜色是如何在0到2之间的数字?@Sweeper我应该以一种与任何视图无关的方式实现模型。所以我的想法是给所有东西一个数字,视图控制器可以决定如何命名它。或者这是一个坏主意?你对“集合匹配”的描述可能会产生误导。对于四个属性中的每一个,卡的三个值必须完全相同或完全相同。三张卡片都是红色和实心的,但颜色和数字都不同,构成了一个有效的集合。请注意,从Swift 4开始,编译器自动合成
=
运算符,它足以声明符合
equalable
协议。@MartinR你是说Swift 4.1?是的,Swift 4.1(与当前的Xcode 9.4.1一起提供)我在答案中插入了您的注释。谢谢!您在游戏集中错过了匹配的概念。这三张卡都是唯一的。您依次查看每个属性。如果每个属性的值相同,或者每个属性的值都不同,则它们匹配。哇,谢谢,这是我一直在寻找的最优雅的解决方案reddit上的ver已经为我提供了使用模运算符的技巧,但不是如何使用。现在我明白了。谢谢!使用结构时也不需要初始值设定项。顺便说一句,最好将所有属性声明为常量。如果以后需要更改,只需创建一个新对象。请注意,将其设置为无序集合您缺少匹配的概念在游戏集合中。这三张牌都是唯一的。你依次查看每个属性。如果它们对每个属性都有相同的值,或者对每个属性都有不同的值,它们就会匹配。我相信如果你只使用集合来比较牌,你不会失去你牌的唯一性。瓦卡瓦马,我更改了它以避免混淆。我希望这能对你有所帮助。