본문 바로가기

내일배움캠프/본캠프 TIL

[TIL] 블랙잭 게임 만들기

이번 시간에는 블랙잭 게임을 한번 구현해보는 시간을 가지겠다.

 

 

 

 

블랙잭은 딜러와 플레이어가 함께 하는 게임으로, 총 점수가 21점이 넘지 않으면서도 딜러와 플레이어 중 21점에 가장 까운 사람이 승리하는 간단한 게임이다.

 

게임 규칙은 다음과 같다.

 

🎯 블랙잭 기본 규칙

  1. 카드 점수
    • 2~10 → 숫자 그대로 점수
    • J, Q, K → 10점
    • A → 1점 또는 11점 (유리한 쪽으로 계산)
  2. 승리 조건
    • 21을 초과하면 버스트(Bust) → 즉시 패배
    • 플레이어가 21 이하로 멈추면, 딜러와 점수를 비교 → 높은 쪽이 승리 (단, 둘 다 21 이하)
  3. 게임 흐름
    1. 플레이어와 딜러에게 카드 2장씩 나눠줌
      • 플레이어는 2장 다 공개
      • 딜러는 1장은 공개, 1장은 비공개
    2. 플레이어는 Hit(카드 더 받기) 또는 Stand(멈추기) 선택
    3. 플레이어가 멈추면 → 딜러 차례
      • 딜러는 17 이상이 될 때까지 무조건 Hit
    4. 딜러와 플레이어 점수 비교 → 승패 결정

 

1. 카드 구현

class Card
{
    public string simbol;
    public string rank;
    public int score;

    public Card(string simbol, string rank, int score)
    {
        this.simbol = simbol;
        this.rank = rank;
        this.score = score;
    }
}

 

딜러와 플레이어가 받을 카드는 다음과 같이 정의하였다.

 

simbol: 포커 카드 이미지 ( "♠", "♥", "♣", "■")

 rank: 포커 카드 문자 (J, Q, K)

score: 포커 카드 점수

 

2. 게임 로직 구현

class GameManager
{
    // 카드 리스트
    private List<Card> deck = new List<Card>();

    // 딜러 카드
    private List<Card> dealerCard = new List<Card>();

    // 플레이어 카드
    private List<Card> playerCard = new List<Card>();

    public GameManager() { }

    public void InitDeck()
    {
        string[] simbols = { "♠", "♥", "♣", "■" };
        string[] ranks = { "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A" };

        foreach (var simbol in simbols)
        {
            foreach (var rank in ranks)
            {
                // 카드 심볼 및 점수 변환
                int score = int.TryParse(rank, out int tmp) ? tmp : (rank == "A" ? 1 : 10);
                deck.Add(new Card(simbol, rank, score));
            }
        }
    }

    public void ShuffleDeck()
    {
        Random random = new Random();
        for (int i = deck.Count - 1; i > 0; i--)
        {
            int j = random.Next(0, i + 1);

            var temp = deck[j];
            deck[j] = deck[i];
            deck[i] = temp;
        }
    }
 }

 

기본적으로 게임 세팅 시 deck을 만들어 총 52장의 카드를 넣어주었다.

또 게임이 시작되기 전 Shuffle을 통해 랜덤하게 카드가 나올 수 있도록 설계하였다.

 

 

// 히트 시 카드 한장 뽑기
public bool Hit()
{
    playerCard.Add(DrawCard());

    if (GetScore(playerCard) > 21) return false;

    return true;
}

// 스코어 구하기
public int GetScore(List<Card> hand)
{
    int sum = hand.Sum(c => c.score);
    int aceCount = hand.Count(c => c.rank == "A");

    // Ace를 11로 계산할 수 있으면 그렇게 함
    while (aceCount > 0 && sum + 10 <= 21)
    {
        sum += 10;
        aceCount--;
    }

    return sum;
}

// 결과 확인
public void Result()
{
    int playerScore = GetScore(playerCard);
    int dealerScore = GetScore(dealerCard);

    if (dealerScore > 21 || playerScore > dealerScore)
        Console.WriteLine("플레이어 승리!");
    else if (playerScore < dealerScore)
        Console.WriteLine("딜러 승리!");
    else
        Console.WriteLine("무승부!");
}

// 카드 배분
public void SettingCard()
{
    // 딜러 2장 뽑기
    dealerCard.Clear();
    dealerCard.Add(DrawCard());
    dealerCard.Add(DrawCard());

    // 플레이어 2장 뽑기
    playerCard.Clear();
    playerCard.Add(DrawCard());
    playerCard.Add(DrawCard());

    // 딜러 차례
    while (GetScore(dealerCard) < 17)
    {
        dealerCard.Add(DrawCard());
    }

}

// Deck에서 카드 뽑기
public Card DrawCard()
{
    Card card = deck[0];
    deck.RemoveAt(0);
    return card;
}

 

게임이 진행되긴 위한 전반적인 게임 시스템 함수는 위과 같다.

다만 'A' 카드는 매우 중요한 카드로 경우에 따라 1 혹은 10점으로 사용할 수 있게 주의하였다.

 

3. 게임 실행

static void Init()
{
    isRunning = true;
    gameManager = new GameManager();
    gameManager.InitDeck();
}

static void Process()
{
    Console.Clear();
    gameManager.ShuffleDeck();
    gameManager.SettingCard();
    gameManager.DisplayDealerCard(false);
    gameManager.DisplayPlayerCard();
    while (isRunning)
    {
        Console.WriteLine();
        Console.Write("hit? (Yes or No): ");

        string input = Console.ReadLine();

        switch (input)
        {
            case "Yes":
                Console.Clear();
                {
                    if (gameManager.Hit() == false)
                    {
                        isRunning = false;
                        gameManager.DisplayDealerCard(false);
                        gameManager.DisplayPlayerCard();
                        Console.WriteLine("21점이 넘었습니다! 게임 종료");
                        break;
                    }
                }
                gameManager.DisplayDealerCard(false);
                gameManager.DisplayPlayerCard();
                Console.WriteLine("카드를 뽑았습니다!");
                break;
            case "No":
                Console.Clear();
                gameManager.DisplayDealerCard(true);
                gameManager.DisplayPlayerCard();
                {
                    gameManager.Result();
                    isRunning = false;
                    break;
                }
                break;
            default:
                Console.WriteLine("입력이 잘못되었습니다.");
                break;
        }
    }
}

 

게임 실행은 플레이어가 Hit 할 것인지 Yes/No를 입력 받게 해서 정말 간단하게 처리하였다.

 

 

동영상 서비스가 종료되어 해당 콘텐츠를 재생할 수 없습니다.