Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
159 views
in Technique[技术] by (71.8m points)

swift - How can I compare 3 values in an array to "not" or "all" equal each other?

The Problem:

I'm building the game Set and I therefore have to choose 3 cards on the board. Each of these cards have four different properties on it:

  • Color (number between 0 and 2)
  • Shape (number between 0 and 2)
  • Shade (number between 0 and 2)
  • Number (number between 0 and 2)

Now I want to compare 3 chosen cards to each other and compute if they are a match or not. I can't just get my head around that because I want to also write it in a good way and not with dozens of for loops.

So we have a match if:

  • All 4 properties are equal to each other on every card
    • Card 1 has red, triangle, 2, striped and Card 2 + 3 also have red, triangle, 2, striped
  • 4 properties are different to each other on every card
    • if card 1 has red, triangly, 2, striped no other card can have one of these

The Assignment

So now I should invent a solution that "according to the teacher" is very simple and my model for this app shouldn't be more then 100 lines of code. Now I'm at almost 100 lines of code and I need to do some more stuff. So I should implement this in a very DRY way.

How would you tackle this problem

I need some guidance to guide me into the right direction. Is there some built in method for arrays I'm missing in Swift or do I need to implement some kind of protocol

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

(Remark: The following solution is tailored for the special case of the Set game, where all three values are 0, 1, or 2. It would not help to check if three arbitrary values are all equal or all different.)

A bit of mathematics helps. If you have three integers x, y, z in the range from 0 to 2, then x+y+z is a multiple of 3 if (and only if)

  • x, y, z are all equal, or
  • x, y, z are all different.

This can be checked with

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

Therefore, if the Card type is defined as

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
}

then the check for a valid set is quite efficiently done with:

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
}

Alternatively, define enumerations with raw values in the range 0, 1, 2 for the various properties:

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
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...