Cesare - 5 months ago 36

Swift Question

This is a struct that contains the operations enabled in the game:

`struct OperationsEnabled {`

var addition = 1

var subtraction = 0 // disabled

var multiplication = 1

var division = 1

}

This is the enum I use to generate simple arithmetic questions:

`enum BinaryOperation: String {`

case Addition = "+"

case Subtraction = "-"

case Multiplication = "×"

case Division = "÷"

func rangesForDifficulty(difficulty: Difficulty) -> (Range<Int>, Range<Int>) {

switch self {

case .Addition:

switch difficulty {

case .Easy: return (1...10, 1...10)

case .Intermediate: return (10...100, 1...100)

case .Difficult: return (109...999, 109...999)

}

case .Subtraction:

switch difficulty {

case .Easy: return (1...10, 1...10)

case .Intermediate: return (10...100, 1...100)

case .Difficult: return (109...999, 109...999)

}

case .Multiplication:

switch difficulty {

case .Easy: return (1...10, 2...4)

case .Intermediate: return (1...50, 3...7)

case .Difficult: return (10...100, 4...15)

}

case .Division:

switch difficulty {

case .Easy: return (1...10, 2...4)

case .Intermediate: return (1...50, 3...7)

case .Difficult: return (10...100, 4...15)

}

}

}

func apply(number1: Int, _ number2: Int) -> Int {

switch self {

case .Addition:

return number1 + number2

case .Subtraction:

return number1 - number2

case .Multiplication:

return number1 * number2

case .Division:

return number1 / number2

}

}

}

// Let's make a new question

func newQuestion() {

let (range1, range2) = binaryOperation.rangesForDifficulty(difficulty)

let number1 = Int.random(range1)

let number2 = Int.random(range2)

let answer = binaryOperation.apply(number1, number2)

}

I want to filter out the operations. For example, I need to exclude the operations not allowed in the game, but there seems to be no way to use conditionals in here. How can I do it?

Answer

You want to choose a random operation from the available operations. Create an initializer for `BinaryOperation`

that takes `OperationsEnabled`

and creates a `BinaryOperation`

.

```
init?(enabled: OperationsEnabled) {
let all: [(BinaryOperation, Int)] = [(.Addition, enabled.addition), (.Subtraction, enabled.subtraction),
(.Multiplication, enabled.multiplication), (.Division, enabled.division)]
let avail = all.flatMap { (op, on) in on == 1 ? op : nil }
if avail.isEmpty {
return nil
}
else {
let index = Int(arc4random_uniform(UInt32(avail.count)))
self = avail[index]
}
}
```

```
let enabled = OperationsEnabled(addition: 1, subtraction: 1, multiplication: 0, division: 0)
let binaryOperation = BinaryOperation(enabled: enabled)!
```

- This works by first creating a paired list of tuples that contain an operation paired with its availability.
`flatMap`

is used to select just those operations that are available.- If none of the operations were marked as available, then
`avail`

will be empty and this*failable*initializer will return`nil`

. - The operation is chosen randomly from the list of available operations.