TIL✏️

[Swift] 숫자 야구 게임

yujjne 2024. 3. 18. 18:00
💡 Goal : 숫자 야구 게임 만들기

 

📝features: 기능 목록

  • 정답을 맞추기 위해 3자리수를 입력하고 힌트를 받습니다
    • 힌트는 야구용어인  스트라이크입니다.
  • 정답은 랜덤으로 만듭니다.(0에서 9까지의 서로 다른 임의의 수 3자리)
  • 완료한 게임들에 대해 시도 횟수 보여주기

 

🪧View

 

 

🧑🏻‍🏫 튜터님 피드백 

 

 

🔧  수정한 부분

  • 깃허브 파일 다운로드 문제 해결 ➡️ .xcodeproj 파일 push
  • .gitignore 파일 추가
  • 고차함수 사용
  • 랜덤 숫자 ➡️ 반복문 외 다른 방법으로 처리
 func makeAnswer() -> [Int] {
    
    let arr = (0...9).map { $0 }
    
    let shuffledArray = arr.shuffled()
    
    if shuffledArray[0] == 0 {
      return [Int](shuffledArray[1...3])
    } else {
      return [Int](shuffledArray[0...2])
    }
  }

 

🫡  회고

저번주보다 난이도 있었던 과제지만 레벨별로 문제 해결하는 과정이 재밌었다.

랜덤 숫자 만드는 로직을 아직 적용하지 못했지만 위의 코드 사용으로 수정해볼 예정이다. 깃허브 Conflict로 골치 아팠는데 gitignore 파일 추가에 대해 더 공부해야겠다.

 

⚙️ 전체 코드

BaseballGame
/*
 Lv6
 - 프로그램을 시작할 때 안내 문구를 보여주세요.
 - 1번 게임 시작하기의 경우 “필수 구현 기능” 의 예시처럼 게임이 진행됩니다.
 - 정답을 맞혀 게임이 종료된 경우 위 안내문구를 다시 보여주세요.
 - 2번 게임 기록 보기의 경우 완료한 게임들에 대해 시도 횟수를 보여줍니다
 - 3번 종료하기의 경우 프로그램이 종료됩니다.
 */
import Foundation

class BaseballGame {
    var answer: Int?
    var isGameRun = true
    let gameManager = GameManager() // 게임을 관리하는 인스턴스 생성
    let recordManager = RecordManager() // 기록을 관리하는 인스턴스 생성
    
    func start() {
        while isGameRun {
            // 정답 생성
            guard let generatedAnswer = makeAnswer() else {
                print("Error: 정답이 생성되지 않았습니다.")
                return
            }
            answer = generatedAnswer
            print("☑️정답: \(answer!)") // 확인용
            
            // 1. 안내문구 출력
            print("""
            ⛳️⚾️ 게임을 시작합니다 ⚾️⛳️
            - - - - - - - - - - - -
            환영합니다!🤗 원하시는 번호를 입력해주세요.
            1. 게임 시작하기  2. 게임 기록 보기  3. 종료하기
            """)
            
            // 2. 유저의 입력값을 받음
            guard let inputMene = readLine() else { continue }
            
            // 3. 입력값에 따라 처리(switch - case 활용해보기)
            switch inputMene {
            case "1":
                print("🏁 게임을 시작합니다")
                recordManager.add(gameManager.playGame(answer!))
            case "2":
                print("📋 게임 기록 보기")
                recordManager.showRecords()
            case "3":
                // 루프 종료
                print("🔚 숫자 야구 게임을 종료합니다")
                isGameRun = false
            default:
                print("올바른 숫자를 입력해주세요!\n")
            }
        }
    }
        
    // MARK: - 정답 만드는 함수
    func makeAnswer() -> Int? {
        var tempNumbers: [Int] = [] // 조건에 맞는 숫자 배열들
        for i in 102...987 {
            let numberString = String(i)
           
            // 정답이 되는 숫자를 0에서 9까지의 서로 다른 3자리의 숫자 (0시작x)
            let numberSet = Set(numberString)
            if numberSet.count == 3 {
            // print("Random three-digit number: \(i)")
                tempNumbers.append(i)
            }
        }
        guard let randomNumber = tempNumbers.randomElement() else { return nil }
        return randomNumber
    }
}

 

GameManager
import Foundation

// MARK: - 게임 실행 관리하는 클래스
class GameManager {
    let numberCount = 3
    func playGame(_ answer: Int) -> Int {
        var trialCount = 0
        while true {
            print("\n숫자를 입력하세요.")
            guard let userInput = readLine() else { continue }
            trialCount += 1
            
            // 2. 문자열 길이 3자리 확인 -> ex) 0456 정수 변환 시 3자리 숫자로 변경
            if userInput.count != numberCount {
                print("⚠️ 올바르지 않은 입력값입니다.")
                continue
            }
            
            // 3. 정수로 변환되지 않는 경우 반복문 처음으로 돌아가기
            guard let userInput = Int(userInput) else {
                print("⚠️ 올바르지 않은 입력값입니다.")
                continue
            }
            
            // 4. 세자리가 아니거나, 0으로 시작되거나 특정 숫자가 두번 사용된 경우 반복문 처음으로 돌아가기
            let inputCheck = Array(String(userInput))
            if Set(inputCheck).count != numberCount || inputCheck[0] == "0" || inputCheck.count != numberCount {
                print("⚠️ 올바르지 않은 입력값입니다.")
                continue
            }
            
            // 5. 정답과 유저의 입력값을 비교하여 스트라이크/볼을 출력하기
            // 만약 정답이라면 break 호출하여 반복문 탈출
            var strike = 0
            var ball = 0
            
            let answerNumbers = Array(String(answer))
            let userInputNumbers = Array(String(userInput))
            
            for (index, number) in userInputNumbers.enumerated() {
                // 입력한 숫자 배열 순회
                // print(index, number)
                if answerNumbers[index] == number {
                    strike += 1
                } else if answerNumbers.contains(number) {
                    ball += 1
                }
            }
            
            if strike == numberCount {
                print("정답입니다!🥳🥳\n게임을 종료합니다.\n")
                break
            } else if strike == 0 && ball == 0 {
                print("Nothing")
            }
            else {
                print("\(strike) strike \(ball) ball")
            }
        }
        return trialCount
    }
}

 

RecordManager
import Foundation

// MARK: - 게임 기록 관리 클래스
class RecordManager {
    var record: [Int] = []
    func add(_ trialCount: Int) {
        record.append(trialCount)
    }
    func showRecords() {
        // 게임 기록
        if record.isEmpty {
            print("게임 결과가 없습니다.")
        }
        for (idx, record) in record.enumerated() {
            print("\(idx+1)번째 게임 : 시도 횟수 - \(record)")
        }
        print()
    }
}