오늘은 야구게임을 만들어 보겠습니다.
야구게임이 뭔지는 잘 찾아보세요.
먼저 클래스 선언부터 해주겠습니다.
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인지 확인합니다.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) { }
num 이 secret 배열에 포함되어 있는지 확인합니다.스트라이크와 볼 확인
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)")
}
}
}