0

I'm in the process of making an app where the user will be quizzed on state capitals. The capital city and the state is presented to the user a UIImage and I have everything working properly. In an effort to reduce code, I am trying to figure out how to avoid all of these "if statements". The "if statements" below just represent four states and capital cities. Imagine these lines forty-six more times. That seems a bit much, right? I've come across Ternary Operators when studying algorithms and tried to use them to reduce this code, but I have had no success. I have two UIImage Arrays - one holds the cities, the other holds the states. The way that my app identifies if the user's answer is correct is matching the corresponding array indices.

Here are my abbreviated arrays ...

let capitalCityList: [UIImage] = [
    UIImage(named: "Montgomery")!,  
    UIImage(named: "Juneau")!,  
    UIImage(named: "Phoenix")!,  
    UIImage(named: "Little Rock")!

let stateWordList: [UIImage] = [
    UIImage(named: "Alabama")!,  
    UIImage(named: "Alaska")!,  
    UIImage(named: "Arizona")!,  
    UIImage(named: "Arkansas")!

Here are the first four "if statements" ...

if capitalCity.image == capitalCityList[0] && stateWord.image == stateWordList[0] {

            scoreInt += 1
            scoreLabel.text = String("Score: \(scoreInt)")

        } else if capitalCity.image == capitalCityList[1] && stateWord.image == stateWordList[1] {

            scoreInt += 1
            scoreLabel.text = String("Score: \(scoreInt)")

        } else if capitalCity.image == capitalCityList[2] && stateWord.image == stateWordList[2] {

            scoreInt += 1
            scoreLabel.text = String("Score: \(scoreInt)")

        } else if capitalCity.image == capitalCityList[3] && stateWord.image == stateWordList[3] {

            scoreInt += 1
            scoreLabel.text = String("Score: \(scoreInt)")

        } else if capitalCityWord.image == capitalCityList[4] && stateWord.image == stateWordList[4] {

            scoreInt += 1
            scoreLabel.text = String("Score: \(scoreInt)")
rmaddy
  • 314,917
  • 42
  • 532
  • 579
  • Possible duplicate of [swift for loop: for index, element in array?](https://stackoverflow.com/questions/24028421/swift-for-loop-for-index-element-in-array) - the [third example in this answer](https://stackoverflow.com/a/50812923/1270789) is closest to what you want, I think. – Ken Y-N Jan 18 '19 at 00:24
  • Ken Y-N ... Is it possible to loop through two enumerated arrays at once and compare the indices? – salanthonyc Jan 18 '19 at 00:56
  • No, but you have the index, so you can use that to look up the second array. – Ken Y-N Jan 18 '19 at 01:03
  • @KenY-N there are better solutions. For example dictionary in this case. You can check my answer – Robert Dresler Jan 18 '19 at 07:13

1 Answers1

1

You're always doing the same thing. You increase score and then you change text of label. So you can do this just with one if statement and since UIImage conforms to protocol Equatable, you can get index of elements as index of image inside an array, so you don't have to create for each loop manually

if let index = capitalCityList.index(of: capitalCity.image),
   capitalCity.image == capitalCityList[index] 
   && stateWord.image == stateWordList[index]  { // these conditions can be written on one line
    scoreInt += 1
    scoreLabel.text = "Score: \(scoreInt)" 
}

anyway, you can have just dictonary with your images in format [image for state: image for city]

let dict = [UIImage(named: "Alabama")!:UIImage(named: "Montgomery")!, ...] 

and then you can just compare if image for state image is equal to capital city image

if dict[stateWord.image] == capitalCity.image {
    scoreInt += 1
    scoreLabel.text = "Score: \(scoreInt)" 
}
Robert Dresler
  • 10,580
  • 2
  • 22
  • 40
  • Thanks for the info. Using two separate arrays works well for me because I am pulling random cities and states from them for the user to try and match correctly. That may be possible with a dictionary too, but I'm not sure. – salanthonyc Jan 18 '19 at 23:46
  • Regarding the first part of your answer, I tried it out and I get this error ... **Value of optional type 'UIImage?' must be unwrapped to a value of type 'UIImage'** If I unwrap with "!", then it crashes. – salanthonyc Jan 18 '19 at 23:54
  • `if let index = capitalCityList.index(of: capitalCity.image)` – salanthonyc Jan 19 '19 at 01:36
  • @salanthonyc and where are you calling this if statement? Maybe you call it in moment when you haven't selected any image yet. – Robert Dresler Jan 19 '19 at 11:14
  • I call it in a startGame function. The user presses a button to start the game. Random capital cities and states appear on screen. The user presses a button if they match. The code posted in my question works perfectly within that function. I am just trying to reduce the length of my code. I'm open to anymore suggestions. But, I think that I need to call it in the startGame function. – salanthonyc Jan 19 '19 at 18:06
  • Another thing ... There should be no reason to check if `capitalCity.image` is nil because it never is. The image is in the Assets folder and capitalCityList is a hard-coded array. – salanthonyc Jan 19 '19 at 18:15