Swift/데모 개발

[Swift] 가위 바위 보 게임 만들기 - Step 2

언클린 2020. 4. 5. 16:42
728x90

이전에 만든 앱에서 디자인과 판 수를 설정할 수 있도록 추가해 보겠습니다. 

디자인은 무료 디자인을 사용했으며 글씨같은 것은 직접 포토샵으로 만들었습니다.

(디자인이 제일 힘든 것 같습니다...)

이번에도 어련운 것은 없기 때문에 빠르게 진행해 보겠습니다.


1. Storyboard에 디자인 작성

이번에는 딱히 화면전환을 만들지 않고 그냥 그 위에 커버 뷰를 하나 생성하여 씌웠다가 표시하고 숨기고 하는 방식으로 진행하였습니다. 향후에 메인 화면 게임 화면을 구성하여 만들고 싶으신 분은 추가해서 대응하시면 될 것 같습니다.

2. 판수 설정

판을 5전 3승과 같이 설정할 수 있도록 하는 메소드를 작성해 보겠습니다.

우선 게임 스타트 버튼을 눌렀을 때 보여지고 있는 커버 뷰를 지우고 이긴 횟 수, 진 횟 수를 초기화 합니다.

그리고 판 수가 입력이 되지 않았을 시 에러 다이어로그를 표시합니다.

(현재의 어플에서는 다른 문자열의 입력값이나 등 정수형 만을 입력할 수 있는 처리는 되어 있지 않습니다.)

private func gameStart() {

        guard let textField = self.stageTextField.text, !textField.isEmpty else {

            let alert = UIAlertController(title: "", message: "판 수를 설정해 주십시오!", preferredStyle: .alert)

            let action = UIAlertAction(title: "OK", style: .default, handler: nil)

            alert.addAction(action)

            self.present(alert, animated: true, completion: nil)

            return

        }

        self.coverView.isHidden = true

        self.stage = Int(textField) ?? 0

        self.winCount = 0

        self.loseCount = 0

    }

과반수 이상일 경우 게임을 끝내고 다시 커버 뷰를 화면에 표시합니다.

private func stageCount() {

        if self.winCount > self.stage / 2 {

            self.coverView.isHidden = false

            self.logoImageView.image = UIImage(named: "win")

        } else if self.loseCount > self.stage / 2 {

            self.coverView.isHidden = false

            self.logoImageView.image = UIImage(named: "lose")

        }

    }

3. 애니메이션 설정

컴퓨터의 가위 바위 보를 애니메이션 화 시킵니다.

애니메이션 스탑과 시작에 맞추어 결과 라벨도 표시하거나 비표시 합니다.

private func startAnimation() {

        self.resultDescriptionLabel.isHidden = true

        self.resultImageView.animationImages = [UIImage(named: "scissors")!,

                                                UIImage(named: "rock")!,

                                                UIImage(named: "paper")!]

        self.resultImageView.animationDuration = 0.5

        self.resultImageView.startAnimating()

    }

    

    private func stopAnimation() {

        self.resultDescriptionLabel.isHidden = false

        self.resultImageView.stopAnimating()

    }

4. 완성 코드

import UIKit

 

class ViewController: UIViewController {

    

    /// Enum Properties

    

    enum ResultState: String {

        case win = "win"

        case draw = "draw"

        case lose = "lose"

    }

    

    enum SRPState {

        case scissors

        case rock

        case paper

        

        var num: Int {

            switch self {

            case .scissors: return 0

            case .rock: return 1

            case .paper: return 2

            }

        }

    }

    

    /// IBOutlet Properties

    @IBOutlet weak var resultImageView: UIImageView!

    @IBOutlet weak var resultDescriptionLabel: UILabel!

    @IBOutlet weak var scissors: UIButton!

    @IBOutlet weak var rock: UIButton!

    @IBOutlet weak var paper: UIButton!

    @IBOutlet weak var coverView: UIView!

    @IBOutlet weak var stageTextField: UITextField!

    @IBOutlet weak var logoImageView: UIImageView!

    

    /// Properties

    

    var winCount = 0

    var loseCount = 0

    var stage: Int = 0

    

    /// Override Methods

    

    override func viewDidLoad() {

        super.viewDidLoad()

        self.initView()

    }

    

    private func initView() {

        self.stageTextField.delegate = self

    }

    

    /// IBAction Methods

    

    @IBAction func didTappedScissors(_ sender: UIButton) {

        self.startProcessing(.scissors)

    }

    

    @IBAction func didTappedRock(_ sender: UIButton) {

        self.startProcessing(.rock)

    }

    

    @IBAction func didTappedPaper(_ sender: UIButton) {

        self.startProcessing(.paper)

    }

    

    @IBAction func didTappedStartButton(_ sender: UIButton) {

        self.gameStart()

    }

}

 

/// MARK:- Process

 

extension ViewController {

    

    /// 결과 출력

    ///

    /// Parameters:

    /// input - 입력한 데이터 값

    private func startProcessing(_ input: SRPState) {

        guard let computerOutput = self.computingState() else {

            print("return value is nil")

            return

        }

        switch input {

        case .scissors:

            switch computerOutput {

            case .scissors: self.resultDescriptionLabel.text = ResultState.draw.rawValue

            case .rock:

                self.resultDescriptionLabel.text = ResultState.lose.rawValue

                self.loseCount += 1

            case .paper:

                self.resultDescriptionLabel.text = ResultState.win.rawValue

                self.winCount += 1

            }

        case .rock:

            switch computerOutput {

            case .scissors:

                self.resultDescriptionLabel.text = ResultState.win.rawValue

                self.winCount += 1

            case .rock: self.resultDescriptionLabel.text = ResultState.draw.rawValue

            case .paper:

                self.resultDescriptionLabel.text = ResultState.lose.rawValue

                self.loseCount += 1

            }

        case .paper:

            switch computerOutput {

            case .scissors:

                self.resultDescriptionLabel.text = ResultState.lose.rawValue

                self.loseCount += 1

            case .rock:

                self.resultDescriptionLabel.text = ResultState.win.rawValue

                self.winCount += 1

            case .paper: self.resultDescriptionLabel.text = ResultState.draw.rawValue

            }

        }

        self.stopAnimation()

        self.stageCount()

    }

    

    /// 컴퓨터의 결과 처리

    ///

    private func computingState() -> SRPState? {

        let computingValue = Int.random(in: 0...2)

        switch computingValue {

        case SRPState.scissors.num:

            self.resultImageView.image = UIImage(named: "scissors")

            return .scissors

        case SRPState.rock.num:

            self.resultImageView.image = UIImage(named: "rock")

            return .rock

        case SRPState.paper.num:

            self.resultImageView.image = UIImage(named: "paper")

            return .paper

        default:

            return nil

        }

    }

    

    /// 판 수 설정

    ///

    private func stageCount() {

        if self.winCount > self.stage / 2 {

            self.coverView.isHidden = false

            self.logoImageView.image = UIImage(named: "win")

        } else if self.loseCount > self.stage / 2 {

            self.coverView.isHidden = false

            self.logoImageView.image = UIImage(named: "lose")

        }

        DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {

            self.startAnimation()

        }

    }

    

    /// 게임 시작

    ///

    private func gameStart() {

        guard let textField = self.stageTextField.text, !textField.isEmpty else {

            let alert = UIAlertController(title: "", message: "판 수를 설정해 주십시오!", preferredStyle: .alert)

            let action = UIAlertAction(title: "OK", style: .default, handler: nil)

            alert.addAction(action)

            self.present(alert, animated: true, completion: nil)

            return

        }

        self.coverView.isHidden = true

        self.stage = Int(textField) ?? 0

        self.winCount = 0

        self.loseCount = 0

        self.startAnimation()

    }

    

    /// 애니메이션 시작

    ///

    private func startAnimation() {

        self.resultDescriptionLabel.isHidden = true

        self.resultImageView.animationImages = [UIImage(named: "scissors")!,

                                                UIImage(named: "rock")!,

                                                UIImage(named: "paper")!]

        self.resultImageView.animationDuration = 0.5

        self.resultImageView.startAnimating()

    }

    

    /// 애니메이션 스탑

    ///

    private func stopAnimation() {

        self.resultDescriptionLabel.isHidden = false

        self.resultImageView.stopAnimating()

    }

}

 

/// MARK:- UITextField Delegate

 

extension ViewController: UITextFieldDelegate {

    func textFieldShouldReturn(_ textField: UITextField) -> Bool {

        textField.resignFirstResponder()

        return true

    }

}

 

5. 실행 하기

이렇게 해서 가위 바위 보 게임을 마치겠습니다. 

추가로 몇 가지 기능을 추가하시고 싶으신 분은 다양하게 활용하셔서 추가하시면 될 것 같습니다.

(난이도 설정이나 버그 방지를 위한 에러 처리 등)

감사합니다.


환경 

Xcode 11.3.1

swift 5

 

728x90