diff --git a/SpartBaseBallGame/SpartBaseBallGame/Sources/BaseBall/BaseBallGame.swift b/SpartBaseBallGame/SpartBaseBallGame/Sources/BaseBall/BaseBallGame.swift index 0e68dc0..c01172d 100644 --- a/SpartBaseBallGame/SpartBaseBallGame/Sources/BaseBall/BaseBallGame.swift +++ b/SpartBaseBallGame/SpartBaseBallGame/Sources/BaseBall/BaseBallGame.swift @@ -11,23 +11,67 @@ import LogMacro actor BaseBallGame { private let digits = 3 - // MARK: - 게임시작 + // MARK: - 게임 시작 func start() async { - #logInfo("게임 시작 — 규칙: 1~9, 서로 다른 \(digits)자리") - _ = makeAnswer() + #logDebug("< 게임을 시작합니다 >") + let answer = makeAnswer() + #logDebug("정답 생성: \(answer)") + + while true { + #logDebug("숫자를 입력하세요") + guard let line = await readLineAsync(), + let guess = parseGuess(from: line) else { + #logDebug("올바르지 않은 입력값입니다") + continue + } + + let result = judge(answer: answer, guess: guess) + + switch result { + case .correct: + #logDebug("정답입니다!") + return + + case .nothing: + #logDebug("Nothing") + + case .strikeAndBall(let strike, let ball): + var parts: [String] = [] + if strike > 0 { parts.append("\(strike)스트라이크") } + if ball > 0 { parts.append("\(ball)볼") } + #logDebug(parts.joined(separator: " ")) + } + } + } + + // MARK: - 입력 파싱 + private func parseGuess(from input: String) -> [Int]? { + let trimmed = input.trimmingCharacters(in: .whitespacesAndNewlines) + guard trimmed.count == digits, + trimmed.allSatisfy({ $0.isNumber }), + !trimmed.contains("0") else { return nil } + let numbers = trimmed.compactMap { Int(String($0)) } + guard Set(numbers).count == digits else { return nil } + return numbers } - // 매 라운드 정답 생성 + // MARK: - 판정 + private func judge(answer: [Int], guess: [Int]) -> JudgeResult { + let strikeCount = zip(answer, guess).filter { $0 == $1 }.count + let ballCount = guess.filter { answer.contains($0) }.count - strikeCount + if strikeCount == answer.count { return .correct } + if strikeCount == 0 && ballCount == 0 { return .nothing } + return .strikeAndBall(strike: strikeCount, ball: ballCount) + } + + // MARK: - 정답 생성 private func makeAnswer() -> [Int] { var pool = Array(1...9) pool.shuffle() - #logDebug("랜덤 숫자", Array(pool.prefix(digits))) return Array(pool.prefix(digits)) } - - - // MARK: - realine + // MARK: - readLine 비동기 래핑 func readLineAsync() async -> String? { await withCheckedContinuation { continuation in Task.detached(priority: .userInitiated) { diff --git a/SpartBaseBallGame/SpartBaseBallGame/Sources/BaseBall/JudgeResult.swift b/SpartBaseBallGame/SpartBaseBallGame/Sources/BaseBall/JudgeResult.swift new file mode 100644 index 0000000..f090d27 --- /dev/null +++ b/SpartBaseBallGame/SpartBaseBallGame/Sources/BaseBall/JudgeResult.swift @@ -0,0 +1,14 @@ +// +// JudgeResult.swift +// SpartBaseBallGame +// +// Created by Wonji Suh on 8/27/25. +// + +import Foundation + +enum JudgeResult { + case correct + case nothing + case strikeAndBall(strike: Int, ball: Int) +} diff --git a/SpartBaseBallGame/SpartBaseBallGame/Sources/GameStart/GameManger.swift b/SpartBaseBallGame/SpartBaseBallGame/Sources/GameStart/GameManger.swift new file mode 100644 index 0000000..25aee43 --- /dev/null +++ b/SpartBaseBallGame/SpartBaseBallGame/Sources/GameStart/GameManger.swift @@ -0,0 +1,17 @@ +// +// GameManger.swift +// SpartBaseBallGame +// +// Created by Wonji Suh on 8/27/25. +// + +import Foundation +import Combine + +actor GameManger { + let baseBall = BaseBallGame() + // MARK: - 야구 게임 시작 + func baseBallGameStart() async { + await baseBall.start() + } +} diff --git a/SpartBaseBallGame/SpartBaseBallGame/Sources/Main/main.swift b/SpartBaseBallGame/SpartBaseBallGame/Sources/Main/main.swift index 15537b2..f3085e3 100644 --- a/SpartBaseBallGame/SpartBaseBallGame/Sources/Main/main.swift +++ b/SpartBaseBallGame/SpartBaseBallGame/Sources/Main/main.swift @@ -7,7 +7,8 @@ import Foundation -let gameManger = GameManager() -await gameManger.baseBallGameStart() +let gameManager = GameManager() + +await gameManager.baseBallGameStart()