Как сократить этот код, чтобы предотвратить дублирование кода?

У меня был этот вопрос довольно долго. Я пытаюсь визуализировать проблему с 3 дверями, просто для удовольствия и практики с Swift. Так что я:

3 двери, и, следовательно, 3 различных IBActions и 3 функции для всех дверей. Все эти функции абсолютно одинаковы, однако в каждом коде различается только количество дверей. Мне было интересно, могу ли я сократить этот код?:

func openSecondChoice(whatDoorIsClickedOn: Int)
    {
        if whatDoorIsClickedOn == 1
        {
            if whatDoorIsClickedOn == doorWithNumber
            {
                UIButtonDoor1.setBackgroundImage( UIImage (named: "doorWithMoney"), for: UIControlState.normal)
            }
            else
            {
                UIButtonDoor1.setBackgroundImage( UIImage (named: "doorWithGoat"), for: UIControlState.normal)
            }
        }
        if whatDoorIsClickedOn == 2
        {
            if whatDoorIsClickedOn == doorWithNumber
            {
                UIButtonDoor2.setBackgroundImage( UIImage (named: "doorWithMoney"), for: UIControlState.normal)
            }
            else
            {
                UIButtonDoor2.setBackgroundImage( UIImage (named: "doorWithGoat"), for: UIControlState.normal)
            }
        }
        if whatDoorIsClickedOn == 3
        {
            if whatDoorIsClickedOn == doorWithNumber
            {
                UIButtonDoor3.setBackgroundImage( UIImage (named: "doorWithMoney"), for: UIControlState.normal)
            }
            else
            {
                UIButtonDoor3.setBackgroundImage( UIImage (named: "doorWithGoat"), for: UIControlState.normal)
            }
        }
    }

Юк! Этот код такой уродливый! Если пользователь нажимает на door1, например, я вызываю функцию "openSecondChoise(whatDoorIsClickedOn: 1)". Есть ли способ сократить это? Спасибо! Я не использую классы здесь, я должен использовать их?

3 ответа

Решение

Обычно, когда вы начинаете суффиксировать имена переменных с 1, 2, 3и т.д., пришло время использовать массив. Для этого и нужны массивы.

С массивом uiButtonDoors который содержит ваш UIButtonDoor1...UIButtonDoor3Ваша функция может выглядеть так:

func openSecondChoice(whatDoorIsClickedOn: Int) {
    let imageName = whatDoorIsClickedOn == doorWithNumber ? "doorWithMoney" : "doorWithGoat"
    uiButtonDoors[whatDoorIsClickedOn - 1].setBackgroundImage(UIImage(named: imageName), for: UIControlState.normal)
}
func openSecondChoice(whatDoorIsClickedOn: Int) {
  let imageName = whatDoorIsClickedOn == doorWithNumber ? "doorWithMoney" : "doorWithGoat"
  let image = UIImage(named: imageName)

  let button: UIButton

  switch whatDoorIsClickedOn {
  case 1:
    button = UIButtonDoor1
  case 2:
    button = UIButtonDoor2
  case 3:
    button = UIButtonDoor3
  default:
    fatalError("Cannot be. Switch must be exhaustive, that's why we need to use 'default' for a switch on Int.")
  }

  button.setBackgroundImage(image, for: .normal)
}

Для более короткой версии проверьте ответ @tuple_cat.

Другой подход, для развлечения.

import UIKit

class DoorGame {
    func setupButtons() {
        let buttons = [UIButton(), UIButton(), UIButton()]

        for (index, button) in buttons.enumerated() {
            button.addTarget(self, action: #selector(buttonTapped(_:)), for: .touchUpInside)
            button.setTitle("\(index)", for: .normal)
        }

        let winningIndex = Int(arc4random_uniform(UInt32(buttons.count)))

        buttons[winningIndex].tag = 1
    }

    @objc func buttonTapped(_ sender: UIButton) {
        let imageName = sender.tag == 1 ? "doorWithMoney" : "doorWithGoat"
        let image = UIImage(named: imageName)

        sender.setBackgroundImage(image, for: .normal)
    }
}
Другие вопросы по тегам