diff --git a/README.md b/README.md index 3b24489..e4ef774 100644 --- a/README.md +++ b/README.md @@ -1,71 +1,72 @@ -# 숫자 야구 게임 과제 (Week 2) -숫자 야구 게임은 1에서 9까지의 서로 다른 3개의 숫자를 맞추는 게임입니다.
-각 레벨마다 기능이 확장되며, 팀원들이 협업하여 매주 주어진 과제를 해결해 나갑니다. - -# 📝 협업 규칙 -### 레포지토리 설정 및 브랜치 관리 -**1** **Fork로 가져오기**: 각 팀원은 레포지토리를 Fork하여 자신의 개인 레포지토리로 가져옵니다.
-**2** **브랜치 생성**: Fork한 개인 레포지토리에서 각자의 이름을 딴 브랜치를 생성합니다.
-**3** **Pull Request**: 과제를 마친 후, 각자의 브랜치로 Pull Request를 생성하여 코드 리뷰를 요청합니다. 모든 팀원이 Pull Request에 코멘트를 달고 피드백을 제공합니다.
-**4** **수정 및 Merge**: 피드백을 반영하여 수정하고, 팀원들의 동의를 얻은 후 merge를 진행합니다.
- -이 과정을 통해 서로의 코드에 대해 이해를 높이고, “왜 이렇게 작성했는지”에 대한 질문과 답변을 주고받으며 과제를 진행합니다. -# 📂 코드 파일 구조 -* main.swift: 게임의 메인 진입점으로, 레벨을 선택하고 시작할 수 있도록 구성되어 있습니다. startGame() 함수가 게임의 시작을 담당합니다. -* Lv_1.swift ~ Lv_6.swift: 각 레벨별 요구사항에 맞게 구현된 파일입니다. 각 파일에는 해당 레벨의 기능을 구현하는 함수가 포함되어 있습니다. - -⠀📜 구현 가이드 - -### main.swift -Command Line Tool 프로젝트에서는 하나의 `main.swift` 파일에서만 프로그램을 시작할 수 있습니다. 따라서 각 레벨별 기능을 별도의 파일로 구현한 후, `main.swift` 파일에서 해당 레벨의 함수를 호출하여 실행하도록 구성합니다. - -```swift -import Foundation - -func startGame() { - print("레벨을 선택하세요 (1, 2, 3, 4, 5, 6):") - - if let input = readLine(), let level = Int(input) { - switch level { - case 1: - levelOne() - case 2: - levelTwo() - case 3: - levelThree() - case 4: - levelFour() - case 5: - levelFive() - case 6: - levelSix() - default: - print("유효하지 않은 레벨입니다. 1~6까지를 선택해주세요.") - } - } else { - print("잘못된 입력입니다.") - } -} - -// 게임 시작 -startGame() -``` -* startGame() 함수에서 게임의 레벨을 선택하여 시작할 수 있도록 구성합니다. -* 사용자가 입력한 레벨 번호에 따라 해당 레벨의 함수를 호출하여 게임을 진행합니다. - - -### 각 레벨 파일 (Lv_1.swift ~ Lv_6.swift) - 구현 파일 - -**Lv_1.swift** - -```swift -import Foundation - -func levelOne() { - // 1. 정답을 생성하는 로직을 추가합니다. - // 2. 유저가 정답을 맞출 때까지 반복해서 입력을 받습니다. - // 3. 입력값이 유효한지 검사하고 힌트를 제공하는 기능을 구현합니다. -} -``` - -각 레벨별로 구현하시면 됩니다. +# Swift로 야구게임 만들기 + +## 📄 개요 +랜덤으로 생성된 3자리 숫자를 맞추는 게임으로, 사용자가 입력한 숫자와 정답을 비교해 결과를 알려주고 기록을 저장합니다. + +## 🛠️ 주요 기능 +- **랜덤 숫자 생성**: 게임 시작 시 서로 다른 3자리 숫자를 생성합니다. +- **입력값 비교**: 사용자가 입력한 숫자와 정답을 비교하여 결과를 반환합니다. +- **게임 기록 저장**: 사용자의 게임 기록을 저장하고 확인할 수 있는 기능입니다. +- **게임 종료**: 사용자가 종료를 원하면 게임이 종료됩니다. + +## ⚠️ 참고사항 +- **랜덤 숫자 생성 제약**: 서로 다른 임의의 숫자 3자리를 생성하며, 첫 자리는 0이 될 수 없습니다. +- **사용자 입력값 예외 처리**: 3자리의 숫자가 아닌 경우 예외 처리가 이루어집니다. + +## ✏️ 상세 설명 +### `BaseballGame` +게임을 시작하고, 기록을 보고 종료하는 기능이 있는 클래스입니다. +
+**selectCategory()** +
+사용자는 게임을 시작하고, 기록을 보고 게임을 종료할 수 있습니다. 올바르지 않은 값을 입력했을 경우 예외 처리했습니다. +
+**gameStart()** +
+랜덤 숫자를 생성하여 사용자의 값과 비교한 뒤 결과를 출력합니다. +
+**printGameHistory()** +
+게임 순서와 게임 시도 횟수를 확인합니다. +
+**gameOver()** +
+게임을 종료합니다. + +### `RandomNumber` +랜덤 숫자를 생성하고 랜덤 숫자와 사용자의 입력값을 비교하는 클래스입니다. +
+**makeRandomNumber** +
+서로 다른 3개의 수를 생성합니다. +
+**compareInput()** +
+랜덤 숫자와 입력값을 비교하여 스트라이크, 볼을 사용하여 결과를 반환합니다. + +### `Result` +게임 결과를 저장하는 열거형으로, `success`, `strikeBall`, `strike`, `ball`, `out`이 있습니다. +
+**printResult()** +
+게임 결과를 출력하는 메서드입니다. + +### `InputError` +사용자의 입력값에 오류가 있는지 확인하는 클래스입니다. +
+**checkInputErrorMain()** +
+메인 화면에서 입력값 오류가 있는지 확인합니다. +
+**checkInputErrorGame()** +
+게임 화면에서 입력값 오류가 있는지 확인합니다. + + + + + + + + + diff --git a/Week2-BaseballGame/Week2-BaseballGame.xcodeproj/project.pbxproj b/Week2-BaseballGame/Week2-BaseballGame.xcodeproj/project.pbxproj index b5ea2cd..0695a57 100644 --- a/Week2-BaseballGame/Week2-BaseballGame.xcodeproj/project.pbxproj +++ b/Week2-BaseballGame/Week2-BaseballGame.xcodeproj/project.pbxproj @@ -249,6 +249,7 @@ isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_STYLE = Automatic; + MACOSX_DEPLOYMENT_TARGET = 15.0; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 5.0; }; @@ -258,6 +259,7 @@ isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_STYLE = Automatic; + MACOSX_DEPLOYMENT_TARGET = 15.0; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 5.0; }; diff --git a/Week2-BaseballGame/Week2-BaseballGame.xcodeproj/xcuserdata/mun.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/Week2-BaseballGame/Week2-BaseballGame.xcodeproj/xcuserdata/mun.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist new file mode 100644 index 0000000..9218389 --- /dev/null +++ b/Week2-BaseballGame/Week2-BaseballGame.xcodeproj/xcuserdata/mun.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -0,0 +1,6 @@ + + + diff --git a/Week2-BaseballGame/Week2-BaseballGame.xcodeproj/xcuserdata/mun.xcuserdatad/xcschemes/xcschememanagement.plist b/Week2-BaseballGame/Week2-BaseballGame.xcodeproj/xcuserdata/mun.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..dfbd5af --- /dev/null +++ b/Week2-BaseballGame/Week2-BaseballGame.xcodeproj/xcuserdata/mun.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,14 @@ + + + + + SchemeUserState + + Week2-BaseballGame.xcscheme_^#shared#^_ + + orderHint + 0 + + + + diff --git a/Week2-BaseballGame/Week2-BaseballGame/InputError.swift b/Week2-BaseballGame/Week2-BaseballGame/InputError.swift new file mode 100644 index 0000000..0f91230 --- /dev/null +++ b/Week2-BaseballGame/Week2-BaseballGame/InputError.swift @@ -0,0 +1,24 @@ +class InputError { + + func checkInputErrorMain(_ input: String?) -> Bool { + guard input!.count == 1, let inputInt = Int(input!) else { + return true + } + + return false + } + + // 입력값이 올바른지 확인하는 메서드 + func checkInputErrorGame(_ input: String?) -> Bool { + // 입력값의 길이가 3이 아니거나, 다른 타입이 있는 경우 + guard input!.count == 3, let inputInt = Int(input!), Set(input!).count == 3 else { + return true + } + // 첫 번째 자리에 0이 있는 경우 + if Array(input!)[0] == "0" { + return true + } + + return false + } +} diff --git "a/Week2-BaseballGame/Week2-BaseballGame/Lv_1(\355\225\204\354\210\230\352\265\254\355\230\204).swift" "b/Week2-BaseballGame/Week2-BaseballGame/Lv_1(\355\225\204\354\210\230\352\265\254\355\230\204).swift" deleted file mode 100644 index afd8aba..0000000 --- "a/Week2-BaseballGame/Week2-BaseballGame/Lv_1(\355\225\204\354\210\230\352\265\254\355\230\204).swift" +++ /dev/null @@ -1,9 +0,0 @@ -// Lv 1 (11/04 까지) -// 1에서 9까지의 서로 다른 임의의 수 3개를 정하고 맞추는 게임입니다 -// 정답은 랜덤으로 만듭니다.(1에서 9까지의 서로 다른 임의의 수 3자리) - -import Foundation - -func levelOne() { - -} diff --git "a/Week2-BaseballGame/Week2-BaseballGame/Lv_2(\355\225\204\354\210\230\352\265\254\355\230\204).swift" "b/Week2-BaseballGame/Week2-BaseballGame/Lv_2(\355\225\204\354\210\230\352\265\254\355\230\204).swift" deleted file mode 100644 index 6930839..0000000 --- "a/Week2-BaseballGame/Week2-BaseballGame/Lv_2(\355\225\204\354\210\230\352\265\254\355\230\204).swift" +++ /dev/null @@ -1,21 +0,0 @@ -// Lv 2 (11/06 까지) - -/* -- 정답을 맞추기 위해 3자리수를 입력하고 힌트를 받습니다 - - 힌트는 야구용어인 **볼**과 **스트라이크**입니다. - - 같은 자리에 같은 숫자가 있는 경우 **스트라이크**, 다른 자리에 숫자가 있는 경우 **볼**입니다 - - ex) 정답 : 456 인 경우 - - 435를 입력한 경우 → 1스트라이크 1볼 - - 357를 입력한 경우 → 1스트라이크 - - 678를 입력한 경우 → 1볼 - - 123를 입력한 경우 → Nothing - - 만약 올바르지 않은 입력값에 대해서는 오류 문구를 보여주세요 -- 3자리 숫자가 정답과 같은 경우 게임이 종료됩니다 -- 실행 예시(정답 : 456)13123213 -*/ - -import Foundation - -func levelTwo() { - -} diff --git "a/Week2-BaseballGame/Week2-BaseballGame/Lv_3(\353\217\204\354\240\204\352\265\254\355\230\204).swift" "b/Week2-BaseballGame/Week2-BaseballGame/Lv_3(\353\217\204\354\240\204\352\265\254\355\230\204).swift" deleted file mode 100644 index d5df17e..0000000 --- "a/Week2-BaseballGame/Week2-BaseballGame/Lv_3(\353\217\204\354\240\204\352\265\254\355\230\204).swift" +++ /dev/null @@ -1,15 +0,0 @@ -// Lv 3 (11/06 까지) - -/* - - 정답이 되는 숫자를 0에서 9까지의 서로 다른 3자리의 숫자로 바꿔주세요 - - 맨 앞자리에 0이 오는 것은 불가능합니다 - - 092 → 불가능 - - 870 → 가능 - - 300 → 불가능 - */ - -import Foundation - -func levelThree() { - -} diff --git "a/Week2-BaseballGame/Week2-BaseballGame/Lv_4(\353\217\204\354\240\204\352\265\254\355\230\204).swift" "b/Week2-BaseballGame/Week2-BaseballGame/Lv_4(\353\217\204\354\240\204\352\265\254\355\230\204).swift" deleted file mode 100644 index f529e37..0000000 --- "a/Week2-BaseballGame/Week2-BaseballGame/Lv_4(\353\217\204\354\240\204\352\265\254\355\230\204).swift" +++ /dev/null @@ -1,24 +0,0 @@ -// Lv 4 (11/07 까지) - -/* - 프로그램을 시작할 때 안내문구를 보여주세요 - // 예시 - 환영합니다! 원하시는 번호를 입력해주세요 - 1. 게임 시작하기 2. 게임 기록 보기 3. 종료하기 - ​ - 1번 게임 시작하기의 경우 “필수 구현 기능” 의 예시처럼 게임이 진행됩니다 - 정답을 맞혀 게임이 종료된 경우 위 안내문구를 다시 보여주세요 - // 예시 - 환영합니다! 원하시는 번호를 입력해주세요 - 1. 게임 시작하기 2. 게임 기록 보기 3. 종료하기 - 1 // 1번 게임 시작하기 입력 - - < 게임을 시작합니다 > - 숫자를 입력하세요 - */ - -import Foundation - -func levelFour() { - -} diff --git "a/Week2-BaseballGame/Week2-BaseballGame/Lv_5(\353\217\204\354\240\204\352\265\254\355\230\204).swift" "b/Week2-BaseballGame/Week2-BaseballGame/Lv_5(\353\217\204\354\240\204\352\265\254\355\230\204).swift" deleted file mode 100644 index f9e0d17..0000000 --- "a/Week2-BaseballGame/Week2-BaseballGame/Lv_5(\353\217\204\354\240\204\352\265\254\355\230\204).swift" +++ /dev/null @@ -1,20 +0,0 @@ -// Lv 5 (11/07 까지) - -/* - 2번 게임 기록 보기의 경우 완료한 게임들에 대해 시도 횟수를 보여줍니다 - // 예시 - 환영합니다! 원하시는 번호를 입력해주세요 - 1. 게임 시작하기 2. 게임 기록 보기 3. 종료하기 - 2 // 2번 게임 기록 보기 입력 - - < 게임 기록 보기 > - 1번째 게임 : 시도 횟수 - 14 - 2번째 게임 : 시도 횟수 - 9 - 3번째 게임 : 시도 횟수 - 12 -*/ - -import Foundation - -func levelFive() { - -} diff --git "a/Week2-BaseballGame/Week2-BaseballGame/Lv_6(\353\217\204\354\240\204\352\265\254\355\230\204).swift" "b/Week2-BaseballGame/Week2-BaseballGame/Lv_6(\353\217\204\354\240\204\352\265\254\355\230\204).swift" deleted file mode 100644 index 848f2d1..0000000 --- "a/Week2-BaseballGame/Week2-BaseballGame/Lv_6(\353\217\204\354\240\204\352\265\254\355\230\204).swift" +++ /dev/null @@ -1,26 +0,0 @@ -// Lv 6 (11/07 까지) - -/* - 3번 종료하기의 경우 프로그램이 종료됩니다 - 이전의 게임 기록들도 초기화됩니다 - // 예시 - 환영합니다! 원하시는 번호를 입력해주세요 - 1. 게임 시작하기 2. 게임 기록 보기 3. 종료하기 - 3 // 3번 종료하기 입력 - - < 숫자 야구 게임을 종료합니다 > - ​ - 1, 2, 3 이외의 입력값에 대해서는 오류 메시지를 보여주세요 - // 예시 - 환영합니다! 원하시는 번호를 입력해주세요 - 1. 게임 시작하기 2. 게임 기록 보기 3. 종료하기 - 4 - - 올바른 숫자를 입력해주세요! -*/ - -import Foundation - -func levelSix() { - -} diff --git a/Week2-BaseballGame/Week2-BaseballGame/RandomNumber.swift b/Week2-BaseballGame/Week2-BaseballGame/RandomNumber.swift new file mode 100644 index 0000000..e3827b5 --- /dev/null +++ b/Week2-BaseballGame/Week2-BaseballGame/RandomNumber.swift @@ -0,0 +1,65 @@ +class RandomNumber { + var randomNumber = [Int]() + + init() { + randomNumber = makeRandomNumber() + } + + // 서로 다른 임의수 3개를 만드는 함수 + func makeRandomNumber() -> [Int] { + // 랜덤 숫자를 저장할 Set 생성 + var randomNumber = [Int]() + + // 서로 다른 숫자가 3개를 생성할 때까지 반복 + while (randomNumber.count < 3) { + let thisRandomNumber = Int.random(in: 0...9) + + // 배열의 첫 요소이고 랜덤 숫자가 0인지 확인 + if thisRandomNumber == 0 && randomNumber.count == 0 { + continue + } + + // 중복값이 없으면 배열에 랜덤 숫자 추가 + if !randomNumber.contains(thisRandomNumber) { + randomNumber.append(thisRandomNumber) + } + } + + // 베열로 변환 후 반환 + return randomNumber + } + + // 랜덤 숫자와 입력값을 비교하는 함수 + func compareInput(_ input: [Int]) -> Result { + // 결과를 저장한 변수 생성 + var strike = 0 + var ball = 0 + + for i in randomNumber.indices { + for j in input.indices { + // 자리&숫자 같으면 스트라이크 + if i == j && randomNumber[i] == input[j] { strike += 1 } + // 숫자만 같으면 볼 + else if randomNumber[i] == input[j] { ball += 1 } + } + } + + let result: Result + + if strike > 0 && ball > 0 { + result = .strikeBall + } else if strike == 3 { + result = .success + } else if strike > 0 { + result = .strike + } else if ball > 0 { + result = .ball + } else { + result = .out + } + + result.printResult(strike: strike, ball: ball) + + return result + } +} diff --git a/Week2-BaseballGame/Week2-BaseballGame/Result.swift b/Week2-BaseballGame/Week2-BaseballGame/Result.swift new file mode 100644 index 0000000..b82ce96 --- /dev/null +++ b/Week2-BaseballGame/Week2-BaseballGame/Result.swift @@ -0,0 +1,23 @@ +// 결과값의 열겨형 +enum Result { + case success + case strikeBall + case strike + case ball + case out + + func printResult(strike: Int, ball: Int) { + switch self { + case .success : + print("정답입니다!\n") + case .strikeBall: + print("\(strike)스트라이크 \(ball)볼\n") + case .strike: + print("\(strike)스트라이크\n") + case .ball: + print("\(ball)볼\n") + case .out: + print("Out\n") + } + } +} diff --git a/Week2-BaseballGame/Week2-BaseballGame/main.swift b/Week2-BaseballGame/Week2-BaseballGame/main.swift index 36bba57..1cb0a31 100644 --- a/Week2-BaseballGame/Week2-BaseballGame/main.swift +++ b/Week2-BaseballGame/Week2-BaseballGame/main.swift @@ -1,29 +1,80 @@ import Foundation -func startGame() { - print("레벨을 선택하세요 (1, 2, 4, 5, 6):") +class BaseballGame { + // 게임 기록을 저장할 2차원 배열 생성 + var gameHistory = [[0],[0]] + // 에러 확인 인스턴스 생성 + let inputError = InputError() - if let input = readLine(), let level = Int(input) { - switch level { - case 1: - levelOne() - case 2: - levelTwo() - case 3: - levelThree() - case 4: - levelFour() - case 5: - levelFive() - case 6: - levelSix() + func selectCategory() { + print("\n환영합니다! 원하시는 번호를 입력해주세요\n 1. 게임 시작하기 2. 게임 기록 보기 3. 종료하기") + + let input = Int(readLine()!) + + switch input { + case 1: gameStart() + case 2: printGameHistory() + case 3: gameOver() default: - print("유효하지 않은 레벨입니다. 1~6까지를 선택해주세요.") + print("\n올바른 숫자를 입력해주세요!") + selectCategory() } - } else { - print("잘못된 입력입니다.") } -} + + func gameStart() { + print("\n< 게임을 시작합니다 >") + // 몇 번째 게임인지 저장 + gameHistory[0].append(gameHistory[0].count) + gameHistory[1].append(0) + + // 랜덤 숫자 인스턴스 생성 + let randomNumber = RandomNumber() + + // 입력값과 결과가 같을 때까지 반복 + while true { + // 입력값을 받고 변수에 저장 + print("숫자를 입력하세요") + let input = readLine() + + // 입력값이 올바른지 확인 + if inputError.checkInputErrorGame(input) == true { + print("올바르지 않은 입력값입니다\n") + continue + } + // 시도 횟수 추가 + gameHistory[1][gameHistory[1].count - 1] += 1 + + // 입력값을 배열로 저장 + let inputArray = input!.map { Int(String($0))! } + + // 정답과 입력값을 비교하고, 성공하면 함수 종료 + if randomNumber.compareInput(inputArray) == .success { + break + } + } + + selectCategory() + } + + func printGameHistory() { + print("\n< 게임 기록 보기 >") + + if gameHistory[0].count > 1 { + for i in 1...gameHistory[0].count - 1 { + print("\(gameHistory[0][i])번째 게임 : 시도 횟수 - \(gameHistory[1][i])") + } + } else { + print("저장된 기록이 없습니다\n2") + } + + selectCategory() + } + + func gameOver() { + print("\n< 숫자 야구 게임을 종료합니다 >") + return + } + } -// 게임 시작 -startGame() +let baseballGame = BaseballGame() +baseballGame.selectCategory()