(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
}