繁体   English   中英

如何比较数组中的3个值,使“不”或“全部”彼此相等?

[英]How can I compare 3 values in an array to “not” or “all” equal each other?

问题:

我正在构建游戏Set ,因此必须在板上选择3张牌。 这些卡中的每一个都有四个不同的属性:

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

现在,我想将3张选定的牌相互比较,并计算它们是否匹配。 我不能只是想办法解决这个问题,因为我也想以一种不错的方式编写它,而不是使用数十个for循环。

因此,如果满足以下条件,我们将有一个匹配项:

  • 每张卡上的所有4个属性都相等
    • 卡1具有红色,三角形2,带条纹,卡2 + 3也具有红色,三角形2,带条纹
  • 每张卡上的4个属性互不相同
    • 如果卡1具有红色,三角形,2,则条纹没有其他卡可以具有其中之一

分配

因此,现在我应该发明一个解决方案,使“根据老师”非常简单,并且我为此应用程序设计的模型不应超过100行代码。 现在,我有近100行代码,还需要做更多的事情。 因此,我应该以非常干燥的方式实现这一点。

您将如何解决这个问题

我需要一些指导以指导我朝正确的方向发展。 在Swift中缺少数组的内置方法吗?还是我需要实现某种协议

注:以下解决方案是为Set游戏的特殊情况量身定制的,其中所有三个值均为0、1或2。这无助于检查三个任意值是否相等或全部不同。)

一点数学会有所帮助。 如果您在0到2的范围内有三个整数x,y,z,则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.
}

因此,如果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
}

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

为了符合Equatable协议,您要做的就是实现此功能:

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)

最后,如果您希望具有一次比较三张卡片的功能,可以将此代码添加到Card类中:

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

您可以这样使用它:

Card.compareThreeCards(firstCard: c1!, secondCard: c2!, thirdCard: c3!)

从Swift 4.1开始,结构和枚举可以免费使用Equatable和Hashable(不适用于Class)。

因此,例如,如果您具有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):设置它为无序集合。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM