Reputation: 23
I am building a Quiz and I have a struct with 4 Variables which are countries.
I have around 15 View Controllers with 4 buttons, each button represents one Country and increments the score by 1.
Now at the end of the Quiz, I want to display the country with the highest score and make it open a new View Controller.
import Foundation
var ukScore = 0
var greeceScore = 0
var italyScore = 0
var austriaScore = 0
var finalCountry = ""
struct QuizScore {
func ukScoreIncrement() {
ukScore += 1
}
func greeceScoreIncrement() {
greeceScore += 1
}
func italyScoreIncrement() {
italyScore += 1
}
func austriaScoreIncrement() {
austriaScore += 1
}
func getFinalScore(){
if ukScore == max(ukScore, greeceScore, italyScore, austriaScore) {
finalCountry = "Uk"
} else if greeceScore == max(ukScore, greeceScore, italyScore, austriaScore) {
finalCountry = "greece"
} else if italyScore == max(ukScore, greeceScore, italyScore, austriaScore) {
finalCountry = "italy"
} else if austriaScore == max(ukScore, greeceScore, italyScore, austriaScore) {
finalCountry = "austria"
}
}
}
`
The idea is to figure out which country wins, and then pass the string to my last class which would then prepare the next segue depending on the winning country.
Upvotes: 2
Views: 124
Reputation: 114975
I would create a struct to represent each country and create an array of these. The struct would have a name and a score.
struct Country: Comparable {
let name: String
var score = 0
mutating func incrementScore() {
self.score += 1
}
static func < (lhs: Country, rhs: Country) -> Bool {
return lhs.score < rhs.score
}
}
Then you can create an array of these structs for whichever countries you need:
var countries = [Country(name:"UK"),
Country(name:"Greece"),
Country(name:"Italy"),
Country(name:"Austria")]
You can then increment scores as required
self.countries[0].incrementScore()
Your winner can then easily be found by sorting the array
let winner = self.countries.sorted().last()!
print("The winner is \(winner.name) with a score of \(winner.score)")
If you use a closure to sort the array then you can have the winner in the first element rather than the last.
To find the winner you could also iterate through the array looking for the maximum score. My thought was that the array is fairly small, so sorting is inexpensive and sorting also gives you second place and third place etc.
Note that normally I wouldn't recommend the use of a force unwrap, but in this case you know the array isn't empty.
Using this approach you can easily create your four buttons by iterating over the array and creating a button for each element. If you add additional Country
instances to the countries
array then your UI would automatically adjust.
Upvotes: 1
Reputation: 7678
Using an enum
with a Dictionary
seems like a better way to model this. Using the .max()
method on Sequence
, you can then easily determine the winner.
enum Country: Hashable {
case uk
case greece
case italy
case austria
}
Using Country
as a key, we then store the score for each.
struct Quiz {
private var scores = [Country: Int]()
/// Add 1 to the score of the given `Country`.
mutating func increment(_ country: Country) {
scores[country, default: 0] += 1
}
/// Determine the winner of the quiz.
/// - returns: The winning `Country`, or `nil` if there are no winners.
func winner() -> Country? {
scores.max { first, second in
// get the maximum score, sorting each dictionary element
// by the score (the .value of the dictionary)
first.value < second.value
}.map { (country, _) in
// transform the resultant element to the "key" value
country
}
}
}
You then have code completion for each possible country, and have a maintainable API.
You can then use a switch
on the result to trigger a segue (or any other code).
var q = Quiz()
q.increment(.uk)
q.increment(.austria)
q.increment(.austria)
let winner = q.winner() // "austria"
switch winner {
case .uk:
triggerUKSegue()
case .greece:
triggerGreeceSegue()
case .italy:
triggerItalySegue()
case .austria:
triggerAustriaSegue()
case nil:
print("no winner yet!")
}
This is just an example, it may be wise to just have a single "result" view, and pass it the winning Country
to display some result.
Additionally, we're not checking if there is more than 1 winner at the moment.
Upvotes: 3