Git Product home page Git Product logo

ios-rock-paper-scissors's Introduction

묵찌빠 게임

📖 목차

  1. 소개
  2. 고민한 점
  3. 타임라인
  4. 실행 화면
  5. 트러블 슈팅
  6. 참고 링크

🌱 소개

woongmene 팀이 만든 콘솔 묵찌빠 게임입니다.

👀 고민한 점

Optional 처리
Control Flow - if 🆚 switch
반복문 🆚 재귀함수
Enumeration - CaseIterable, rawValue
NameSpace, Magic Literal
method 기능 분리 - 단일 책임

⏰ 타임라인

Step 1

  • 220823

    • Hand 타입 enum 설정 ➡️ case .paper .rock .paper
    • 게임 전체를 실행해 줄 gameStart 함수 구현
    • 사용자 입력을 받아 Hand 타입으로 반환하는 makeUserHand 함수 구현
    • 랜덤 컴퓨터 핸드와 유저 핸드를 비교하는 함수 checkResult 구현
    • checkResult 함수에서 유저 입력이 0일 경우, 게임 종료 로직 추가
    • Hand Enum에서 사용하지 않는 불필요한 Int 타입 rawValue 삭제
    • STEP 1 PR 작성 ➡️ PR 보러가기

  • STEP 1 Refactoring

    • RockPaperScissors.swift 파일에서 Hand enum을 파일로 분리
    • 전역변수를 사용하지 않기 위해 gameStopCheck 변수와 randomComputerHand 상수 함수 내부로 이동
    • 가위바위보 결과값을 연결해주는 Result enum 파일 생성 ➡️ case .win .lose .draw
    • Result enum rawValue String 타입으로 설정하고compareHand 함수에서 결과 출력 시 rawValue 사용하도록 리팩토링
    • compareHand 함수에서 반환된 Result타입의 rawValue를 출력하는 displayResult함수 분리 (메서드별로 한가지 기능만 하도록 의도함.)
    • makeUserHand 함수 리팩토링
      guard let inputNumberString = readLine(),
        let inputNumber = Int(inputNumberString),
        let result = Hand(rawValue: inputNumber) else {
      
      print(GameMessages.inputWrong)
      return startGame()
      }
      
    • 'startGame' 함수에서 재귀함수 이용하여 반복구현하도록 리팩토링
      • while구문을 통해 게임을 반복시키지 않고, startGame() 함수 내부에서 startGame()을 호출하는 재귀함수 활용
  • 220824

    • compareHand 함수 파라미터 수정 및 Tuple로 승패 처리하도록 리팩토링
      • argument lable 사용
        func compareHand(with computer: Hand, and user: Hand) -> Result {
    • makeUserHand 함수 삭제하고 startGame 함수 내부에서 그 역할을 동시에 수행하도록 수정
    • compareHand 함수 .draw 조건 default 에서 처리하도록 변경 및 gameStart함수명 startGame으로 변경

Step 2

  • 220824

    • MukJjiPpa Type enum으로 구현 ➡️ case .none .muk .jji .ppa
    • MukJjiPpaResult Type enum으로 구현 ➡️ case .win .lose .draw
    • 묵찌빠 게임을 진행하는 playMukJjiPpaGame 함수 구현
    • 사용자와 컴퓨터의 묵찌빠를 비교하여 MukJjiPpaResult를 반환하는 compareMukJjiPpa 함수 구현
    • 비교된 함수를 받아서 게임을 실행하는 playMukJjiPpaGame함수 부분 구현
    • startGame 함수의 게임 재시작 조건 수정
    • MukJjiPpaResult enum rawValue 수정, 코딩 컨벤션 통일
    • STEP 2 PR 작성 ➡️ PR 보러가기
  • 220825

    • STEP 2 Refactoring
      • while true loop 사용하지 않기 위해, 사용자턴을 알려주는 Player enum 생성
      • 매직리터럴 제거를 위해 GameMessages enum 생성하고 String 이동
      • 삼항연산자를 사용하여 누구의 턴인지 출력하는 if문 삭제, playMukJjiPpaGame 함수에서 turn 매개변수 생성 및 Player enum으로 턴 주고받을 수 있게 변경
      • playMukJjiPpaGame 함수에서 묵찌빠 비교해서 결과를 출력하는 부분을displayMukJjiPpaResult함수로 분리
      • 새로 생성된 enum 파일의 주석 (Created by woong, mene)로 변경

💻 실행 화면

가위바위보 오류처리
draw & win
가위바위보 lose
묵찌빠 오류처리 & 종료
가위바위보 win
묵찌빠 lose & draw(종료)

❓ 트러블 슈팅

  • 함께 작업하는 원격 Repository pull 했을 때 main 브랜치만 노출되는 문제

    • 처음에는 Collaborator에 woong을 등록하지 않아서 생기는 문제인가 했는데 이후에도 step2 진행하면서 새로 생성한 step2 브랜치가 노출되지 않는 문제가 있었습니다. git branch명령으로 확인해보아도 main만 노출되어 git branch -a명령으로 확인해보니 step2 브랜치 네임이 빨간색으로 표시되어 git checkout step2로 브랜치 변경하고 계속해서 진행할 수 있었습니다.
  • readLine()으로 받아온 옵셔널 값 처리 guard에서 0,1,2,3의 Int값을 받아 사용 ➡️ 함수 내부에서 Hand 타입으로 바로 변경

    guard let inputNumberString = readLine(), let inputNumber = Int(inputNumberString),
              inputNumber >= 0, inputNumber < 4 else {
            print("잘못된 입력입니다. 다시 시도해주세요.")
            continue
            }

    처음 작성했던 코드는 readLine에서 받아온 옵셔널 스트링값을 Int 타입으로 변환해서 0...3 사이인지 확인하고 Int로 반환된 값을 다시 사용하는 방식이었는데(이때는 Hand 타입에도 .scissor .rock .paper만 존재)

    guard let inputNumberString = readLine(),
    let inputNumber = Int(inputNumberString),
    let result = Hand(rawValue: inputNumber) else {

    rawValue를 사용해서 해당하는 Hand 타입을 매칭하는 방식으로 리팩토링하였습니다.(Hand 타입에도 0에 대응하는 .none 케이스 추가)

  • Hand 타입에서 .none 케이스 처리

    그에 따라 guard문에서 0,1,2,3을 받아서 처리할 때에는 임의의 컴퓨터 핸드를 만들어주는 randomComputerHand 상수도

    let randomComputerHand: Hand = Hand.allCases.randomElement().unsafelyUnwrapped

    enum의 CaseIterable 프로토콜을 이용해서 allCases.randomElement()로 정의해서 사용하다가 Hand 타입으로 직접 변환하게 되면서 0이 입력되면 가위/바위/보 가 아닌 none이 생성될 수 있는 문제가 있어서

    let randomComputerHand: Hand = Hand(rawValue: Int.random(in: 1...3)).unsafelyUnwrapped

    .none을 제외하고 1...3 사이의 Hand만 랜덤하게 생성되도록 수정하였습니다.

  • 종료조건 턴 확인 ➡️ Bool 타입의 isuserTurn 전역변수 사용 대신 Player enum 활용

    기존에는 승패 여부를 isUserTurn이라는 Bool 타입의 전역변수로 정의하고 관리하였습니다. 그것을 활용하여 승패를 조건으로 while문이 작동하도록 하였습니다.

    func gameStart() {
        while isUserTurn {

    변경 후, playMukJjiPpaGame 함수의 파라미터로 누구의 턴인지 Player 타입으로 받아서 턴과 결과를 튜플로 비교하여 승패 여부를 판단하도록 수정하였습니다.

    func playMukJjiPpaGame(turn: Player) {
        switch (turn, mukJjiPpaResult)
    }
  • 매직 리터럴과 NameSpace 타입

    • MagicLiteral: 따로 변수나 상수에 할당하지 않은 리터럴을 아무 설명 없이 코드에 집어 넣는 것.
    • MagicNumber: 나무위키에서는 이를 설명없이 무작정 등장하는 숫자라고 표현한다.
      • 이번 프로젝트에서는 매직넘버와 리터럴 사용을 하지 않기 위해 노력해 보았습니다.
    • NameSpace에 대해 새롭게 알게 되었습니다. 네임 스페이스는 관련있는 값들을 모아놓은 공간인데 struct 타입으로 설정하거나 enum으로 설정해 줄 수 있습니다. struct 타입으로 설정 시 협업을 하는 개발자들이 실수로 인스턴스를 생성할 수 있는 가능성이 있기 때문에 private init()을 통해 인스턴스화 할 수 없도록 하거나 enum으로 생성해야 합니다.
      • 게임 내에서 사용되는 모든 메세지들을 GameMessages라는 이름의 enum 타입의 NameSpace를 생성하여 호출하도록 리팩토링 하였습니다.
    enum GameMessages {
    static let mukJjiPpaGameMemu: String = "턴] 묵(1), 찌(2), 빠(3)! <종료 : 0> :"
    static let inputWrong: String = "잘못된 입력입니다. 다시 시도해주세요."
    static let endGame: String = "게임종료"
    static let victory: String = "의 승리!"
    static let rockPaperScissorGameMenu: String = "가위(1), 바위(2), 보(3)! <종료 : 0> :"
    }

🔗 참고 링크

Swift API Design Guidelines - Naming
Swift Language Guide - Control Flow
Swift Language Guide - Functions
Swift Language Guide - Enumerations
Swift Language Guide - Properties
Swift Language Guide - Methods
Swift에서의 namespace
매직넘버-나무위키


🔝 맨 위로 이동하기

ios-rock-paper-scissors's People

Contributors

jaekimdev avatar ios-woong avatar yagom avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.