숫자 야구게임(Swift)

이득령·2024년 6월 17일

swift

목록 보기
4/9

오늘은 야구게임을 만들어 보겠습니다.

야구게임이 뭔지는 잘 찾아보세요.

먼저 클래스 선언부터 해주겠습니다.

class BaseballGame {

}

랜덤숫자 생성

다음으로는 3자리 숫자를 중복없이 1 부터 9까지 숫자를 뽑아주는 함수를 만들어 줄게요

함수선언

func makeAnswer() -> Int { }

이 함수는 반환타입이 Int 입니다.

변수선언 밑 초기화

var number = [Int]()

비여있는 정수배열을 만들어 주고 여기에 랜덤숫자 3개를 저장할 것입니다.

3개의 숫자 생성

while number.count < 3 { }
  • 랜덤숫자 생성
    let num = Int.random(in: 1...9)
    num 이라는 상수를 만들어주고 ‘1’ 부터 ‘9’ 까지의 수를 num 에 저장합니다. 랜덤숫자 중복 검사
    if !number.contains(num) {
        number.append(num)
    }

    contains은 컬렉션타입에서 특정 요소가 있는지 Bool 타입으로 값을 내는 메서드

    number 배열에 num 이 포함 되어있는지 확인 하고 값을 포함 합니다.

배열을 정수로 변환 밑 반환

return number.reduce(0) { $0 * 10 + $1 }

reduce는 배열의 모든 요소를 결합하여 하나의 값으로 만드는 함수 입니다.

return 과 동시에 배열을 숫자로 변환 해줍니다. (임의 숫자 [4,3,2])

number = [4, 3, 2] 를 reduce를 통해 3자리 숫자로 만들어줍니다

  • 계산 방식: 초기값을 0 으로 잡습니다. 계산방식은 $0 * 10 + $1입니다. $0 초기값인 0이 들어가고 $1에는 number의 처음 값인 4가 들어갑니다 0 + 10 * 4 = 4 이렇게 계산이 됩니다.

유저입력 처리

입력 요청

print("3자리 숫자를 입력하세요 (예: 123): ", terminator: "")

User에게 3자리 숫자를 입력 하도록 요청합니다

terminator: "" 은 출력후 줄 바꿈으 ㄹ하지 않도록 설정합니다.

유효성 감사

guard let input = readLine(), input.count == 3, let number = Int(input) else {
    print("유효하지 않은 입력입니다. 3자리 숫자를 입력해주세요.")
    return nil
}
  • readLine() 을 사용하여 User 입력을 읽습니다
  • input.count == 3 는 입력된 문자열의 길이가 3인지 확인합니다.
  • let number = Int(input) 는 입력된 문자열이 정수로 변환 가능한지 확인합니다

문자열을 배열로 배열로 변환

let digits = Array(String(number)).compactMap { $0.wholeNumberValue }
  • String(number) 는 숫자를 문자열로 변환합니다.
  • Array(String(number)) 는 문자 배열로 변환합니다.
  • compactMap { $0.wholeNumberValue } 는 각 문자를 정수로 변환하여 새로운 배열을 만듭니다

확인 및 반환

return digits.count == 3 ? digits : nil
  • 변환한 배열 digits 의 길이가 3인지 확인합니다.
  • 길이가 3이면 배열을 반환하고, 그렇지 않으면 nil 을 반환합니다.

스트라이크, 볼 추론

함수 만들기

func calculateScore(secret:[Int], guess:[Int]) ->(strikes:Int, balls: Int)
  • 이 함수는 두개의 정수 배열인 secret, guess 를 인자로 받습니다.
  • 반환타입은 (strikes: Int, balls: Int) 로 스트라이크와 볼의 수를 반환합니다.

초기화

var strikes = 0
var balls = 0
  • strikes, balls 변수를 각각 0으로 초기화합니다.
  • strikes 는 정확한 위치와 값을 맞춘 횟수를 balls 는 값은 맞췄지만 위치가 틀린 횟수를 의미합니다.

반복문, 인덱스 열거

for (i, num) in guess.enumerated() { }

enumerated 메서드는 시퀀스(배열, 문자열 등) 을 각 요소와 해당 요소의 인덱스를 함께 튜플로 반환함

열거는 여러 개의 항목이나 요소를 하나씩 차례로 나열, 카운트 하는것

  • guess 배열을 열거하여 각 요소의 인덱스와 값을 가져옵니다.

시크릿 숫자 배열에 포함 여부 확인

if secret.contains(num) { }
  • numsecret 배열에 포함되어 있는지 확인합니다.
  • 포함되어 있으면 다음 조건을 확인합니다.

스트라이크와 볼 확인

if secret[i] == num {
    strikes += 1
} else { 
    balls += 1 
}
  • secret[i] == num 조건은 guess 배열의 현제 인덱스 i 에서의 값 num 이 배열의 같은 인텍스에 있는 값과 일치 하는지 확인합니다.
  • 일치하면 strikes 를 1증가 시킵니다.
  • 일치하지 않으면 ball 를 1증가 시킵니다.

전체코드

//MARK: - BaseballGame
class BaseballGame {
    //MARK: - 전역변수 선언
    var functionCallCount = 0
    var gameCount = [Int]()
    var currentNumber = 1
    var tryCount = [Int]()
    //MARK: - 랜덤숫자 만들기
    func makeAnswer() -> Int {
        var number = [Int]()
        while number.count < 3 {
            var num: Int = 0
            if (number.isEmpty) {
                num = Int.random(in: 1...9)
            } else {
                num = Int.random(in: 0...9)
            }
            if !number.contains(num) {
                number.append(num)
            }
        }
        return number.reduce(0) { $0 * 10 + $1 }
    }
    //MARK: - 유저입력 처리
    func getUserInput() -> [Int]? {
        print("3자리 숫자를 입력하세요 (예: 123): ", terminator: "")
        guard let input = readLine(), input.count == 3, let number = Int(input) else {
            print("유효하지 않은 입력입니다. 3자리 숫자를 입력해주세요.")
            return nil
        }
        
        let digits = Array(String(number)).compactMap { $0.wholeNumberValue }
        return digits.count == 3 ? digits : nil
    }
    
    //MARK: - 스트라이크, 볼 추론
    func calculateScore(secret:[Int], guess:[Int]) ->(strikes:Int, balls: Int) {
        var strikes = 0
        var balls = 0
        
        for (i, num) in guess.enumerated() {
            if secret.contains(num) {
                if secret[i] == num {
                    strikes += 1
                } else { balls += 1 }
            }
            
        }
        return (strikes, balls)
    }
    //MARK: - 게임 구동
    func Start() {
        functionCallCount += 1
        let secretNumber = Array(String(makeAnswer())).compactMap { $0.wholeNumberValue }
        var attempts = 0
        var isRunning = true
        print(secretNumber)
        
        while isRunning {
            attempts += 1
            
            guard let userInput = getUserInput() else { continue }
            
            let score = calculateScore(secret: secretNumber, guess: userInput)
            print("스트라이크: \(score.strikes), 볼: \(score.balls)")
            if score.strikes == 3 {
                print("축하합니다! \(attempts)번 만에 맞추셨습니다.")
                print("< 숫자 게임이 끝났습니다. >")
                gameCount.append(currentNumber)
                currentNumber += 1
                tryCount.append(attempts)
                isRunning = false
                MainMenu()
            }
            
        }
    }
    //MARK: - 게임 시작 메뉴
    func MainMenu() {
        var isRunning = true
        while isRunning {
            if functionCallCount == 0 {
                print("환영합니다! 원하시는 번호를 입력해주세요")
                print("1. 게임 시작하기  2. 게임 기록 보기  3. 종료하기")
                print("선택: ", terminator: "")
            } else {
                print("1. 게임 시작하기  2. 게임 기록 보기  3. 종료하기")
                print("선택: ", terminator: "")
            }
            guard let choice = readLine(), let option = Int(choice) else {
                print("유효하지 않은 입력입니다. 다시 시도해주세요.")
                continue
            }
            switch option {
            case 1:
                print("게임을 시작합니다!")
                Start()

            case 2:
                print("게임 기록을 보여줍니다.")
                showGameLog()
            case 3:
                print("< 숫자 게임을 종료합니다. >")
                isRunning = false
            default:
                print("유효하지 않은 선택입니다. 다시 시도해주세요.")
            }
        }
    }
    //MARK: - 게임기록확인 함수
    func showGameLog() {
        for(num1, num2) in  zip(gameCount, tryCount) {
            print("\(num1)번째 게임 : 시도 횟수 - \(num2)")
        }
    }

}
profile
프로그래머 아님

0개의 댓글