2025.01.29 (수)

윤혜진·2025년 1월 29일
1

TIL

목록 보기
14/41

📍오늘의 학습 키워드

  • 3주차 과제
    • 블랙잭 게임 만들기

📍학습 내용

  • 블랙잭 게임 만들기
    • 사실 블랙잭보다 스네이크 게임이 먼저지만, 나보다 진도가 빠르신 분들이 스네이크 게임보다 블랙잭 구현이 더 쉬울 거란 조언을 주셔서 스네이크 게임을 먼저 만들어보기로 했다.
    • 다행히 게임의 기본 골자는 튜터님이 이미 다 구현해 두신 상태였고, 나는 딜러 클래스와 블랙잭 클래스만 구현하면 되는 상황이었음.
    • 아래는 내가 생각한 블랙잭 게임의 흐름을 정리한 것 :
      [시작]
      - 시작할 때 플레이어와 딜러 모두 카드를 2장씩 뽑는다
      - 카드의 합을 출력해준다.
      
      [플레이어의 턴]
      - 카드 뽑기 권유(y/n)
          - 카드를 뽑는다면(y):
              - 뽑은 카드 출력
              - 현재 총합 출력
              - 플레이어의 총합이 21을 넘는지 확인
                  - 넘는다면 바로 게임 종료
          - 카드를 뽑지 않는다면:
              - 플레이어의 턴 종료
      
      [딜러의 턴]
      - 딜러의 총합이 17 미만이라면
          - 카드 뽑기
              - 뽑은 카드 출력
              - 현재 총합 출력
              - 딜러의 총합이 21을 넘는지 확인
                  - 넘는다면 바로 게임 종료
      - 17 이상이라면
          - 카드 뽑지 않고 넘기기 (턴 종료)
      
      [두 사람 모두 턴 종료를 선언]
      - 플레이어와 딜러의 총합 비교
          - 플레이어 > 딜러:
              - 플레이어의 승리입니다!
          - 플레이어 < 딜러:
              - 딜러의 승리입니다!
          - 플레이어 == 딜러:
              - 무승부입니다!
    • 게임의 흐름을 정리해보니, 플레이어의 턴과 딜러의 턴 모두 아래와 같은 과정을 반복적으로 실행하는 것을 알 수 있었음.
      - 카드 뽑기
              - 뽑은 카드 출력
              - 현재 총합 출력
              - 딜러의 총합이 21을 넘는지 확인
                  - 넘는다면 바로 게임 종료
    • 때문에 이 과정을 다음과 같은 메서드로 묶어주기로 했다.
      1. 카드를 뽑고, 뽑은 카드와 총합을 출력하는 Draw 메서드:

        • 현재 누구의 턴인지 Player 타입 매개변수를 받아온다.
        • player 클래스의 DrawCardFromDeck 매서드로 덱에서 카드를 뽑은 뒤, 출력해준다.
        • 마찬가지로 GetTotalValue 매서드를 총해 player의 총합을 받아오고, 출력해준다.
        public void Draw(Player player)
        {
            //이름 받아오기
            string name = player.name;
        
            //카드 뽑기 실행 및 뽑은 카드 저장
            string cardName = player.DrawCardFromDeck(deck).ToString();
        
            //현재 총합 받아오기
            int total = player.Hand.GetTotalValue();
        
            //누구의 턴인지 명시
            Console.WriteLine($"{name}의 차례입니다.");
        
            //뽑은 카드 출력, 현재 총합 출력
            Console.WriteLine($"{name}는 '{cardName}'을(를) 뽑았습니다. 현재 총합은 {total}점 입니다.");
        
        }
      2. 두 플레이어가 21점을 초과했는지 확인하는 메서드:

        • Player 타입 매개변수를 받아오고, true 혹은 false 값을 반환하는 메서드.
        • true가 반환되면 게임이 종료되도록 설계했다.
        • 총합 21점을 넘었다면 초과 문구와 승리 문구를 출력하고, true를 반환해준다.
        • 총합이 21점이거나, 21점 아래라면 ScoreCheck 메서드를 실행하고, ScoreCheck메서드에서 반환된 값을 그대로 다시 반환한다.
        public bool CheckGameOver(Player player)
        {
            //플레이어나 딜러가 21점을 초과했는지 확인하는 메서드
            int total = player.Hand.GetTotalValue();
        
            string name = player.name;
            string enemy = player.enemyName;
        
            if (total > 21)
            {
                Console.WriteLine($"{name}의 카드 합이 21점을 초과했습니다. {enemy}의 승리입니다.");
                return true;
            }
            else
            {
                return ScoreCheck();
            }
        
        }
      3. 두 플레이어의 총합을 비교하는 메서드:

        • CheckGameOver 메서드에서 카드 합이 21이하인 것을 확인한 후에 진입하는 메서드
        • 마찬가지로 true 혹은 false를 반환한다.
        • drawEnd : 카드 뽑기를 중단할 경우 true가 되는 변수
        • 즉, 플레이어와 딜러 모두가 카드 뽑기를 멈추고, 21을 넘지 않았다면: 두 플레이어의 총합을 비교하고 승패를 출력, ture를 반환함.
        • 만약 한 플레이어라도 카드 뽑기를 멈추지 않았다면: false를 반환함.
        public bool ScoreCheck()
        {
            //플레이어와 딜러의 총합을 비교해주는 메서드
            int playerTotal = player.Hand.GetTotalValue();
            int dealerTotal = dealer.Hand.GetTotalValue();
        
            if (dealer.drawEnd && player.drawEnd)
            {
                if (playerTotal > dealerTotal)
                {
                    Console.WriteLine("플레이어의 승리입니다.");
                }
                else if (playerTotal < dealerTotal)
                {
                    Console.WriteLine("딜러의 승리입니다.");
                }
                else
                {
                    Console.WriteLine("무승부입니다.");
                }
        
                return true;
            }
            
            return false;
        }

📍겪은 어려움

  • 블랙잭 클래스를 구현하려는데 오류가 뜸 :

    • 어제도 본 오류였다. 이번에는 abstract를 사용하지도 않았는데 같은 오류가 떠서 굉장히 당황했음…
    • 알고보니 abstract의 문제가 아니라 클래스의 본문에 Console을 작성해서였다.
    • 클래스의 내부에는 필드, 메서드, 속성 같은 구성 요소만 정의가 가능하기 때문에, Console같은 코드는 클래스 내부에 메서드를 만든 뒤, 그 안에 넣어주어야 오류가 나지 않는다는 듯.
    • 해결: MainGame 메서드를 만들어 Console 코드를 넣자 정상적으로 실행되었다.
  • 카드가 제대로 더해지지 않는 오류 발생 :

    • 사실 이 카드 합을 계산해주는 부분은 튜터님께 제공받은 부분이었기 때문에 당최 무엇이 문제인지 알 수 없었다.
    • 고민하다가 블랙잭을 만든 다른 분에게도 같은 오류가 나는지 여쭤봤는데, 그 분은 이런 오류가 발생하지 않는다고 하셨음.
    • 추측: 블랙잭에는 Ace카드를 1 혹은 11로 사용할 수 있는 룰이 있는데, 내가 초기 카드로 에이스를 뽑고, 그 이후에 한 번 더 에이스를 뽑으면서 위와 같은 상황이 일어난게 아닌가 싶다.
  • 딜러 행동 로직 구현 중 override 실패 :

    • 딜러의 행동 로직을 구현하는 과정에서 override를 사용해보려고 했는데, DrawCardFromDeck 메서드는 Card를 반환해야 종료되는 메서드였기 때문에,내가 반환하고 싶지 않은 상황(딜러의 총합이 17 이상인 상황)에서도 무의미하게 Card를 반환해주어야 하는 문제가 생겼음.
    • 때문에 void 메서드로 바꿔주려고 했으나, override를 하려면 매개변수와 반환 타입이 같아야하므로 결국 override를 사용하는 방법은 포기할 수 밖에 없었다.
    • 결국 총합 17 이하일 때만 카드를 뽑는 로직은 Dealer 클래스 내부가 아닌 Blackjack 클래스에서 구현하게 되었는데… 나중에 다 만들고 나서야 굳이 override가 아니라도 일반 메서드로 구현했으면 되지 않았을까? 하는 생각이 들어서 뒤늦게 아차 했다.

📍회고 및 반성

  • 딜러의 행동 로직을 Dealer 클래스 내부에서 구현해야 했는데, 블랙잭 안에서 처리한 점이 아쉽다…
  • 이렇게 여러 클래스를 이용해서 코드를 짜본건 처음인데, 미리 코드를 제공받지 않았으면 이렇게 세부적으로 나눌 수 있었을까? 싶음.
  • 필드를 선언할 때마다 프로퍼티를 사용하긴 했지만, 아직 내가 이걸 전부 이해하고 쓴다는 느낌이 안 드는 것 같다. (그냥 쓰니까 쓴다는 느낌…) 다음에 코드를 짤 때는 프로퍼티를 좀 더 제대로 이용하고 적극적으로 사용하고 싶음!

0개의 댓글

관련 채용 정보