[Project] 숫자 야구 게임 ➁

JJOOEE__·2024년 6월 14일
0

Today I Learned....

목록 보기
8/19
post-thumbnail

🍏 Lv. 3

  • 정답이 되는 숫자를 0에서 9까지의 서로 다른 3자리의 숫자로 바꿔주세요

    • 맨 앞자리에 0이 오는 것은 불가능합니다
      • 092 → 불가능
      • 870 → 가능
      • 300 → 불가능
  • makeAnswerNum 함수
    첫번째 자리 숫자가 0이 아닌 서로 다른 3자리 랜덤 숫자 생성 함수

func makeAnswerNum() -> [Int] {
  var numbers = [Int]()
    while numbers.count < 3 {
      let randomNum = Int.random(in: 0...9)
        // 숫자가 비어있거나 0이면 초기화하고 첫번째 숫자부터 다시 생성
        if numbers.isEmpty && randomNum == 0 {
            numbers.removeAll()
            continue
            }
            // 생성된 숫자가 배열에 포함되어 있지 않을때만 배열에 추가됨
            if !numbers.contains(randomNum) {
                numbers.append(randomNum)
            }
        }
        return numbers
    }
  }

⬜ 코드 작성하며 공부한 내용

🌈 배열 메서드 활용 👈 클릭시 배열 메서드로 이동

  • isEmpty
    • 배열이 비어 있는지 확인
    • array1.count == 0 이 구문보단, array1.isEmpty를 사용
  • removeAll()
    • 모든 요소를 제거

🌈 == 연산자 활용

  • 동등 비교 연산자 (==)
    두 값이 서로 같으면 참을 반환합니다.
    예를 들어, x == y는 x와 y가 동일한지 확인합니다.

  • 부등 비교 연산자 (!=)
    두 값이 서로 다르면 참을 반환합니다.
    예를 들어, x != y는 x와 y가 다른지 확인합니다.

  • 크기 비교 연산자 (>, <, >=, <=)
    >: 왼쪽 값이 오른쪽 값보다 크면 참을 반환합니다.
    <: 왼쪽 값이 오른쪽 값보다 작으면 참을 반환합니다.
    >=: 왼쪽 값이 오른쪽 값보다 크거나 같으면 참을 반환합니다.
    <=: 왼쪽 값이 오른쪽 값보다 작거나 같으면 참을 반환합니다.
    예를 들어, x > y는 x가 y보다 큰지 확인합니다.

🌈 볼과 스트라이크를 계산하는 함수를 따로 생성

func clcStrikeBall(answerNum: [Int], userNum: [Int]) -> (strike: Int, ball: Int) {
    var strike = 0
    var ball = 0
    
    for (index, digit) in userNum.enumerated() {
        if answerNum[index] == digit {
            strike += 1
        } else if answerNum.contains(digit) {
            ball += 1
        }
    }
    
    return (strike, ball)
}

🍏 Lv. 4

class BaseballGame {
    func game() {
      outer: while true {

          print("환영합니다, 원하는 번호를 선택하세요!")               // 사용자에게 입력값을 받음
            print(" 1. 게임 시작     2. 기록 보기    3. 게임 종료 ")
            if let option = readLine(), let choice = Int(option) {
                switch choice {
                case 1:                                         // 게임 시작
                    gameStart()
                case 2:                                         // 기록보기
                    recordView()
                case 3:                                         // 게임종료
                    print("< 숫자 야구 게임을 종료합니다 >")
                    break outer
                default:
                    print("올바른 숫자를 입력하세요")
                }
            }
        }
    }
}

🍏 Lv. 5

  • 2번 게임 기록 보기의 경우 완료한 게임들에 대해 시도 횟수를 보여줍니다
// 기록보기함수 : 1....n번 게임에서의 시도 횟수를 확인
// 1번째 게임 시도 횟수를 값으로 저장, 2번째 게임의 시도 횟수를 값으로 저장 .....[ 배열로 저장 ]

var records = [Int]()   // 각 게임의 시도 횟수를 저장하는 배열

func recordView() {
    if records.isEmpty {
        print("게임 기록이 없습니다.")
    } else {
        for (index, tries) in records.enumerated() {
            print("\(index+1)번째 게임: 시도 횟수 _ \(tries)")
        }

    }
}

🍏 Lv. 6

  • 3번 종료하기의 경우 프로그램이 종료됩니다
    이전의 게임 기록들도 초기화됩니다
// 예시
환영합니다! 원하시는 번호를 입력해주세요
1. 게임 시작하기  2. 게임 기록 보기  3. 종료하기
3 // 3번 종료하기 입력

< 숫자 야구 게임을 종료합니다 > 
  • 1, 2, 3 이외의 입력값에 대해서는 오류 메시지를 보여주세요
// 예시
환영합니다! 원하시는 번호를 입력해주세요
1. 게임 시작하기  2. 게임 기록 보기  3. 종료하기
4

올바른 숫자를 입력해주세요!

⬜ 코드 작성하며 공부한 내용

🌈 case 3선택해서 게임을 종료하기

  • 라벨 사용 : 라벨을 통해 외부 루프에서 탈출
  • 커스텀 종료 함수 사용 : 게임 종료를 처리하는 별도의 함수를 작성하여 이 함수를 호출하여 게임을 종료
 //생략
 
 case3:
 endGame()
 
 //생략
 
func endGame() {
  print("< 숫자 야구 게임을 종료합니다 >")
  // 종료에 필요한 추가 로직 작성
  // 예를 들어, 파일을 닫거나 리소스를 해제하는 등의 작업 수행 가능
  exit(0) // 프로그램 종료
  • 플래그 변수 사용하기
    특정 상태를 나타내는 플래그 변수를 도입하여 해당 변수의 상태에 따라 루프를 계속할지 중단할지 결정
 //생략
 
while gameEnded {
~~~~

case3 :                                      // 게임종료
      print("< 숫자 야구 게임을 종료합니다 >")
      gameEnded = false // 게임 종료 상태로 변경

💡 월요일 제출 전까지 해야 할 일:

  • 주석 추가하여 코드 목적 설명 및 함수/변수 역할 명시 필요
  • 간결한 표현식으로 변경하여 가독성 향상 필요
  • 변수명과 함수명 변경하여 이해도 높이기
  • 함수와 클래스 활용도 개선
  • 중복 코드 제거
  • 필요하다면 swift파일 분리

lv. 1 ~ 6 코드 생성 완료 > 수정 필요 단계

//  BaseballGame.swift
//  BaseballGame
//
//  Created by  on 6/13/24.
//

import Foundation

let game = BaseballGame()
game.game()


func isValidNumber(userNum: Int) -> Bool {

    // 세 자리 수인지 확인
    if userNum < 100 || userNum > 999 {
        print("세 자리 수를 입력해주세요.")
        return false
    }
    // 중복된 숫자가 있는지 확인,
    // 숫자 > 문자열 > 문자의 집합 count를 통해 요소 숫자가 3인지 확인하여 중복숫자 검사
    let userNumStr = String(userNum)
    let numSet = Set(userNumStr)
    if numSet.count != 3 {
        print("특정 숫자가 두 번 사용되었습니다. 다시 입력해주세요.")
        return false
    }
    return true
}

// BaseballGame 클래스 외부에 위치한 사용자가 입력한 숫자와 정답 숫자의 스트라이크와 볼을 계산하는 함수
// 힌트출력 : 같은숫자 같은자리 스트라이크, 같은숫자 다른자리 볼, 다른숫자 다른자리 아웃
// randomNum & userNum > 배열로 변환하여  각 자리 별 비교
// if, else if, else 조건문 사용하여 각각 선언

func clcStrikeAndBall(answerNum: [Int], userNum: Int) -> (strike: Int, ball: Int) {
    let userNumArray = Array(String(userNum)).compactMap { Int(String($0)) }
    var strike = 0
    var ball = 0

    for (index, digit) in userNumArray.enumerated() {
        if answerNum[index] == digit {
            strike += 1
        } else if answerNum.contains(digit) {
            ball += 1
        }
    }
    return (strike, ball)
}

func makeAnswerNum() -> [Int] {
    var numbers = [Int]()
    while numbers.count < 3 {
        let randomNum = Int.random(in: 0...9)
        // 숫자가 비어있거나 0이면 초기화하고 첫번째 숫자부터 다시 생성
        if numbers.isEmpty && randomNum == 0 {
            numbers.removeAll()
            continue
        }
        // 생성된 숫자가 배열에 포함되어 있지 않을때만 배열에 추가됨
        if !numbers.contains(randomNum) {
            numbers.append(randomNum)
        }
    }
    return numbers
    }

func gameStart() {
    let answerNum = makeAnswerNum()
    print(answerNum)
    // 정답을 만드는 함수
    var tries = 0           // 현재 게임의 시도 횟수를 기록할 변수

    while true {
        // 사용자에게 새자리 숫자 입력값을 받음
        print("< 게임을 시작합니다 >")
        print("숫자를 입력하세요 : ", terminator: "")

        if let input = readLine(), let userNum = Int(input) {
            if isValidNumber(userNum: userNum) {
                tries += 1

                let (strike,ball) = clcStrikeAndBall(answerNum: answerNum, userNum: userNum)
                if strike == 3 {
                    records.append(tries)
                    print(" 정답입니다. 처음으로 돌아갑니다 ")
                    break 
                    // 게임이 종료되면 반복문 탈출
                }
                if strike == 0 && ball == 0 {
                    print(" OUT( NOTHING ) ")
                } else {
                    var output = ""
                    if strike > 0 {
                        output += "strike: \(strike)"
                    }
                    if ball > 0 {
                        output += (output.isEmpty ? "" : ", ") + "ball: \(ball)"
                    }
                    print("(\(output))", terminator: "")
                }
            }
        }
    }
}
// 기록보기함수 : 1....n번 게임에서의 시도 횟수를 확인
// 1번째 게임 시도 횟수를 값으로 저장, 2번째 게임의 시도 횟수를 값으로 저장 .....[배열로 저장]

var records = [Int]()   // 각 게임의 시도 횟수를 저장하는 배열


func recordView() {
    if records.isEmpty {
        print("게임 기록이 없습니다.")
    } else {
        for (index, tries) in records.enumerated() {
            print("\(index+1)번째 게임: 시도 횟수 _ \(tries)")
        }

    }
}


class BaseballGame {
    func game() {
      outer: while true {

          print("환영합니다, 원하는 번호를 선택하세요!")               // 사용자에게 입력값을 받음
            print(" 1. 게임 시작     2. 기록 보기    3. 게임 종료 ")
            if let option = readLine(), let choice = Int(option) {
                switch choice {
                case 1:                                         // 게임 시작
                    gameStart()
                case 2:                                         // 기록보기
                    recordView()
                case 3:                                         // 게임종료
                    print("< 숫자 야구 게임을 종료합니다 >")
                    break outer
                default:
                    print("올바른 숫자를 입력하세요")
                }
            }
        }
    }
}
  1. isValidNumber 함수 내의 세 자리 수 확인 조건문을 간소화
  2. func makeAnswerNum() numbers조건문 연산자 활용해서 간소화
  3. func makeAnswerNum(), func recordView() 따로 분리하여 생성
    > func recordView() 시작시 초기화 해주는 값이기 때문에 시작할때 필요한 값 두가지 한번에 생성할 수있도록 묶어주면 편할 것 같음
profile
개발이 어려운 나를 위한... 개발노트

0개의 댓글