혼자만의 미니 프로젝트

Swift | Command Line Tools로 만든 숫자야구게임 만들기

ziziDev 2024. 6. 16. 15:49
반응형

초등학생 시절..

수업시간에 연습장 펴고 몰래 했던 숫자야구게임을

과제로 받게되었다

 

룰따윈.. 너무 잘 알기 때문에 어떤걸 사용해서 구현할 지 고민하였다

 

기록용관리 매니저

게임 로직

시작화면

이렇게 세 클래스로 나눠서 진행을 하였다

 

기록관리용

RecordManager

몇 번째 게임에 시도횟수를 관리하는용도 + 3스트라이크 했을 시 기록관리에 데이터가 추가되는 용도 이기 때문에

recordValue를 Int형 배열로 만들어 getValues와 updateValue로 만들면 될것같다라고 생각했다

 

시작화면에 들어가게되면

게임 / 기록 / 게임종료 / 이외의 숫자나 문자를 누르게되면 "올바른 숫자를 다시 입력하세요"가 나오도록 해야하므로

우선 enum으로 ViewType으로 설정하고 시작 / 기록 / 나가기 케이스를 만들어주고

startGame 함수가 호출되면 while구문으로 누르는 버튼에 따라서 실행하면 될것같다라고 생각했습니다

 

그리고 게임로직은

컴퓨터에서 랜덤 숫자 생성을 배열로 잡고

시도횟수

게임 시작할 때 초기화해주는 메서드와

유효성검사 / 유효성 검사완료 후 ball, strike판별 함수로 넘어가게끔 작성하면 될것 같다 생각한 후 작업을 했습니다

 

enum ViewType: Int {
    case start = 1
    case record
    case exit
}

class RecordManager  {
    private var recordValues: [Int] = []

    func updateValue(_ value: Int) {
        recordValues.append(value)
    }

    func getValues() {

        if recordValues.isEmpty {
            print("기록이 없습니다 게임을 시작하세요")
        } else {
            print("⭐️ 게임 기록 ⭐️")
            recordValues.enumerated().map { idx, record in
                print("\(idx + 1)번째 게임 : 시도 횟수 - \(record)")
            }
        }
    }
}

class SceneManager {
    private let recordManager: RecordManager
    private let game: BaseballGame

    init(recordManager: RecordManager, game: BaseballGame) {
        self.recordManager = recordManager
        self.game = game
    }

    func startGame() {
        while true {
            print("환영합니다! 원하시는 번호를 입력해주세요 \n 1. 게임 시작하기  2. 게임 기록 보기  3. 종료하기")
            guard let pick = readLine(), let option = Int(pick) else {
                print("올바른 숫자를 입력하세요")
                continue
            }
            switch option {
            case 1 :
                game.startGame()
                break
            case 2 :
                recordManager.getValues()
            case 3 :
                print("게임종료")
                return
            default :
                print("올바른 숫자를 다시 입력하세요")

            }

        }
    }
}

class BaseballGame {
    private var answer: [Int] = []
    private var attempt: Int = 0
    private var record: RecordManager
    init(record: RecordManager) {
        self.record = record
    }

    private func updateRandomNumber() {
//        var answer = Array(0...9).shuffled().prefix(3).map{ $0 }
//        while answer.contains(0) {
//            answer = Array(0...9).shuffled().prefix(3).map{ $0 }
//        }

        var answer = Array(Array(1...9).shuffled().prefix(3))

        self.answer = answer
        //print("⭐️ \(answer) ⭐️")
    }

    func startGame() {
        answer = []
        attempt = 0
        updateRandomNumber()
        playGame()

    }

    func validationNumber(number: String) -> [Int]? {
        guard number.count == 3, let checkNum = Int(number) else { return nil }
        let digit = String(checkNum).compactMap { $0.wholeNumberValue }
        return Set(digit).count == 3 && !digit.contains(0) ? digit : nil

    }

    func checkNumber(_ number: [Int]) -> (strike: Int, ball: Int) {
        let strike = zip(number, answer).filter { $0 == $1 }.count
        let ball = number.filter { answer.contains($0) }.count - strike
        return (strike, ball)
    }

    func incrementAttemp() {
        attempt += 1
    }

    func playGame() {

        while true {
            print("숫자를 입력하세요")

            guard let value = readLine(), let checkNum = validationNumber(number: value) else {
                print("올바르지 않은 입력값입니다 다시 입력하세요")
                continue
            }

            incrementAttemp()

            let valid = checkNumber(checkNum)

            if valid.strike != 3 {
                print("\(valid.strike)strike \(valid.ball)ball")
            }
            else {
                record.updateValue(attempt)
                print("빙고 입니다")
                break
            }
        }
    }
}

let recordManager = RecordManager()
let baseballGame = BaseballGame(record: recordManager)
let sceneManager = SceneManager(recordManager: recordManager, game: baseballGame)
sceneManager.startGame()

 

하지만 여기서 마음에 들지 않는 점이

recordManager는 고유하기 때문에 굳이 저렇게 여기저기 넣을 필요 없이 딱 한번 선언하고 사용하면 되지 않을까라는 생각이 들어서 기록 매니저를 싱글톤 패턴으로 변경하였습니다

 

import Foundation


enum ViewType: Int {
    case start = 1
    case record
    case exit
}

class RecordManager  {
    private var recordValues: [Int] = []

    static let instance = RecordManager()
    
    private init() {
        
    }
    
    func updateValue(_ value: Int) {
        recordValues.append(value)
    }

    func getValues() {

        if recordValues.isEmpty {
            print("기록이 없습니다 게임을 시작하세요")
        } else {
            print("⭐️ 게임 기록 ⭐️")
            recordValues.enumerated().map { idx, record in
                print("\(idx + 1)번째 게임 : 시도 횟수 - \(record)")
            }
        }
    }
}

class SceneManager {
    private let game: BaseballGame

    init(game: BaseballGame) {
        self.game = game
    }

    func startGame() {
        while true {
            print("환영합니다! 원하시는 번호를 입력해주세요 \n 1. 게임 시작하기  2. 게임 기록 보기  3. 종료하기")
            guard let pick = readLine(), let option = Int(pick) else {
                print("올바른 숫자를 입력하세요")
                continue
            }
            switch option {
            case 1 :
                game.startGame()
                break
            case 2 :
                RecordManager.instance.getValues()
            case 3 :
                print("게임종료")
                return
            default :
                print("올바른 숫자를 다시 입력하세요")

            }

        }
    }
}

class BaseballGame {
    
    private let recordManager:RecordManager
    
    private var answer: [Int] = []
    private var attempt: Int = 0
    
    init(recordManager: RecordManager) {
        self.recordManager = recordManager
    }
    
    private func updateRandomNumber() {
//        var answer = Array(0...9).shuffled().prefix(3).map{ $0 }
//        while answer.contains(0) {
//            answer = Array(0...9).shuffled().prefix(3).map{ $0 }
//        }

        var answer = Array(Array(1...9).shuffled().prefix(3))

        self.answer = answer
        //print("⭐️ \(answer) ⭐️")
    }

    func startGame() {
        answer = []
        attempt = 0
        updateRandomNumber()
        playGame()

    }

    func validationNumber(number: String) -> [Int]? {
        guard number.count == 3, let checkNum = Int(number) else { return nil }
        let digit = String(checkNum).compactMap { $0.wholeNumberValue }
        return Set(digit).count == 3 && !digit.contains(0) ? digit : nil

    }

    func checkNumber(_ number: [Int]) -> (strike: Int, ball: Int) {
        let strike = zip(number, answer).filter { $0 == $1 }.count
        let ball = number.filter { answer.contains($0) }.count - strike
        return (strike, ball)
    }

    func incrementAttemp() {
        attempt += 1
    }

    func playGame() {

        while true {
            print("숫자를 입력하세요")

            guard let value = readLine(), let checkNum = validationNumber(number: value) else {
                print("올바르지 않은 입력값입니다 다시 입력하세요")
                continue
            }

            incrementAttemp()

            let valid = checkNumber(checkNum)

            if valid.strike != 3 {
                print("\(valid.strike)strike \(valid.ball)ball")
            }
            else {
                RecordManager.instance.updateValue(attempt)
                print("빙고 입니다")
                break
            }
        }
    }
}

let baseballGame = BaseballGame(recordManager: RecordManager.instance)
let sceneManager = SceneManager(game: baseballGame)
sceneManager.startGame()

 

반응형

'혼자만의 미니 프로젝트' 카테고리의 다른 글

UIKit | 계산기 만들기  (0) 2024.06.06
UIKit | 팀소개 만들기 - 1일차  (0) 2024.05.30