최근 진행하고 있는 스파르타 부트캠프 과제로 블랙잭 만들기가 주어졌습니다.
따라서 오늘은 C# 콘솔 환경에서 블랙잭 게임을 구현 해보겠습니다.
1. 블랙잭 규칙
블랙잭 게임은 카지노에서 흔히 볼 수 있는 게임으로 카드의 합이 21에 가까운 사람이 승리하는 간단한 규칙의 게임입니다.
게임이 시작되면 딜러와 플레이어는 카드를 2장씩 받게 됩니다.
만약 이때 플레이어의 카드의 합이 21이면 그 즉시 블랙잭으로 승리하게 됩니다.
단, 딜러 카드의 합 또한 21이면 무승부 처리됩니다.
딜러는 무조건 카드의 합이 17이상 되도록 카드를 뽑아야하기 때문에 어떻게 보면 플레이어가 조금 유리한 게임이라고
할 수 있습니다. 하지만, 딜러와 플레이어 모두 21이 넘었을 경우에는 무조건 플레이어의 패배이기 때문에 플레이어는 이점을 유의하면서 플레이해야합니다.
이외의 여러가지 룰이 존재하지만 간단하게 만들어보는 것이 목표이기 때문에 따로 구현하지 않겠습니다.
- 과제의 요구사항
1. 블랙잭 게임은 1명의 플레이어와 1명의 딜러가 참여합니다.
2. 게임 시작 시, 플레이와 딜러는 각각 두 장의 카드를 받습니다.
3. 플레이어는 21점이 넘지 않는 한 계속해서 카드를 받을 수 있습니다.
4. 딜러는 카드의 합이 17점이 되거나 넘을 때까지 계속해서 카드를 받아야 합니다.
5. 카드를 더 이상 받지 않는 플레이어와 딜러 중 카드 합이 21점에 더 가까운 쪽이 승리합니다.
6. 21점을 초과하면 패배합니다.
2. 구현 내용
이번 과제는 제공된 코드가 굉장히 잘 되어있고 규칙도 간단해서 어렵지 않게 구현했던 것 같습니다.
따라서 굳이 풀어서 설명하지 않고 코드만 보여줘도 구현 의도가 보이기 때문에 아래 구현 코드로 대체하겠습니다.
-구현 코드
namespace BlackJack
{
using System;
using System.Collections.Generic;
using System.Security.Cryptography.X509Certificates;
public enum Suit { Hearts, Diamonds, Clubs, Spades }
public enum Rank { Two = 2, Three, Four, Five, Six, Seven, Eight, Nine, Ten, Jack, Queen, King, Ace }
// 카드 한 장을 표현하는 클래스
public class Card
{
public Suit Suit { get; private set; }
public Rank Rank { get; private set; }
public Card(Suit s, Rank r)
{
Suit = s;
Rank = r;
}
public int GetValue()
{
if ((int)Rank <= 10)
{
return (int)Rank;
}
else if ((int)Rank <= 13)
{
return 10;
}
else
{
return 11;
}
}
public override string ToString()
{
return $"{Rank} of {Suit}";
}
}
// 덱을 표현하는 클래스
public class Deck
{
private List<Card> cards;
public Deck()
{
cards = new List<Card>();
foreach (Suit s in Enum.GetValues(typeof(Suit)))
{
foreach (Rank r in Enum.GetValues(typeof(Rank)))
{
cards.Add(new Card(s, r));
}
}
Shuffle();
}
public void Shuffle()
{
Random rand = new Random();
for (int i = 0; i < cards.Count; i++)
{
int j = rand.Next(i, cards.Count);
Card temp = cards[i];
cards[i] = cards[j];
cards[j] = temp;
}
}
public Card DrawCard()
{
Card card = cards[0];
cards.RemoveAt(0);
return card;
}
}
// 패를 표현하는 클래스
public class Hand
{
private List<Card> cards;
public Hand()
{
cards = new List<Card>();
}
public void AddCard(Card card)
{
cards.Add(card);
}
public int GetTotalValue()
{
int total = 0;
int aceCount = 0;
foreach (Card card in cards)
{
if (card.Rank == Rank.Ace)
{
aceCount++;
}
total += card.GetValue();
}
while (total > 21 && aceCount > 0)
{
total -= 10;
aceCount--;
}
return total;
}
//보유중인 카드 이름 얻기
public string GetHaveCradsName()
{
string names = "";
foreach(Card card in cards)
{
names += ", " + card.ToString();
}
return names;
}
}
// 플레이어를 표현하는 클래스
public class Player
{
public Hand Hand { get; private set; }
public Player()
{
Hand = new Hand();
}
//덱에서 카드를 뽑아서 핸드에 추가
public Card DrawCardFromDeck(Deck deck)
{
Card drawnCard = deck.DrawCard();
Hand.AddCard(drawnCard);
return drawnCard;
}
}
// 딜러 클래스를 작성하고, 딜러의 행동 로직을 구현하세요.
public class Dealer : Player
{
//핸드의 합이 17 이상이 될 때까지 카드 뽑기
public void DrawRemainCard(Deck _deck)
{
while(Hand.GetTotalValue() < 17)
{
DrawCardFromDeck(_deck);
}
}
}
// 블랙잭 게임을 구현하세요.
public class Blackjack
{
//참가자
public Player player = new Player();
public Dealer dealer = new Dealer();
//덱
public Deck deck = new Deck();
//승리자
public bool isPlayerWin = false;
public bool isDealerWin = false;
// 코드를 여기에 작성하세요
//게임시작
public void StartGame()
{
//카드 그만 받기
bool stopDraw = false;
//플레이어와 딜러가 두장 씩 카드를 뽑음
player.DrawCardFromDeck(deck);
dealer.DrawCardFromDeck(deck);
player.DrawCardFromDeck(deck);
dealer.DrawCardFromDeck(deck);
//블랙잭이 존재한다면 즉시 게임 종료
if (player.Hand.GetTotalValue() == 21 || dealer.Hand.GetTotalValue() == 21)
GameEnd(player, dealer);
//플레이어는 21점이 넘지 않는 한 카드를 계속 받을 수 있음
while (player.Hand.GetTotalValue() <= 21 && !stopDraw)
{
Console.Clear();
Console.WriteLine("블랙잭");
Console.WriteLine();
Console.WriteLine("현재 보유중인 카드 : {0}", player.Hand.GetHaveCradsName());
Console.WriteLine("현재 패의 합계 : {0}", player.Hand.GetTotalValue());
Console.WriteLine("카드를 더 받으시겠습니까?");
Console.WriteLine();
Console.WriteLine("1. 예");
Console.WriteLine("2. 아니오");
string input = Console.ReadLine();
switch (input)
{
case "1":
player.DrawCardFromDeck(deck);
break;
case "2":
stopDraw = true;
break;
}
dealer.DrawRemainCard(deck);
}
//플레이어의 카드 합이 21이 넘었을 경우
if(player.Hand.GetTotalValue() > 21)
{
Console.Clear();
Console.WriteLine("블랙잭");
Console.WriteLine();
Console.WriteLine("현재 보유중인 카드 : {0}", player.Hand.GetHaveCradsName());
Console.WriteLine("현재 패의 합계 : {0}", player.Hand.GetTotalValue());
Console.WriteLine();
Console.WriteLine("보유중인 카드합이 21이 넘어 더 이상 카드를 뽑으실 수 없습니다.");
Console.WriteLine();
Console.WriteLine("게임 결과를 확인하시려면 아무키나 입력하세요.");
Console.ReadLine();
}
//게임 끝
GameEnd(player, dealer);
}
//게임 결과 보여주기
public void GameEnd(Player _player, Dealer _dealer)
{
//게임 결과 확인
GameReferee(_player, _dealer);
Console.Clear();
Console.WriteLine("블랙잭");
Console.WriteLine();
Console.WriteLine("게임결과");
Console.WriteLine("---------------------------------------------------------------------------");
Console.WriteLine();
Console.WriteLine("플레이어 보유카드 : {0}", _player.Hand.GetHaveCradsName());
Console.WriteLine("플레이어 합 : {0}", _player.Hand.GetTotalValue());
Console.WriteLine();
Console.WriteLine("딜러 보유카드 : {0}", _dealer.Hand.GetHaveCradsName());
Console.WriteLine("딜러 합 : {0}", _dealer.Hand.GetTotalValue());
Console.WriteLine();
if (isPlayerWin)
Console.WriteLine("플레이어의 승리!!");
else if (isDealerWin)
Console.WriteLine("딜러의 승리!!");
else { Console.WriteLine("무승부!!"); }
}
//게임 심판
public void GameReferee(Player _player, Dealer _dealer)
{
int playerTotal = _player.Hand.GetTotalValue();
int dealerTotal = dealer.Hand.GetTotalValue();
//둘다 21점 이하일 경우 점수가 더 적은 사람이 승리
if ((playerTotal <= 21 && dealerTotal <= 21))
{
int playerScore = Math.Abs(21 - playerTotal);
int dealerScore = Math.Abs(21 - dealerTotal);
if (playerScore < dealerScore)
isPlayerWin = true;
else if (dealerScore < playerScore)
isDealerWin = true;
}
//딜러의 승리 조건
else if ((playerTotal > 21 && dealerTotal <= 21) || playerTotal > 21)
isDealerWin = true;
//플래이어의 승리 조건
else if (dealerTotal > 21 && playerTotal <= 21 && !isDealerWin)
isPlayerWin = true;
}
}
class Program
{
static void Main(string[] args)
{
Blackjack blackjack = new Blackjack();
Console.WriteLine("블랙잭");
Console.WriteLine();
Console.WriteLine("게임을 시작하려면 아무키나 입력하세요.");
Console.ReadLine();
// 블랙잭 게임을 실행하세요
blackjack.StartGame();
}
}
}
3. 시연영상
4. 후기
이번 과제를 하면서 많이 배웠던 점은 Card, Deck, Hand, Player, Dealer, BlackJack와 같이 생각보다 정말 세세하게
Class를 나눠서 작업을 한다는 점을 배웠던 것 같습니다. 또한 나눈 객체들 마다 필요한 것들이 전부 담겨있으니
이후 Blackjack이라는 하나의 게임을 만들 때 훨씬 수월하게 게임을 만들 수 있었던 것 같습니다.
앞으로 어떤 게임을 만들려고 할 때, 게임에 필요한 것들을 생각한 뒤, 여러가지의 객체로 쪼개서 필요한 것들을 구현하고
이후 만든 객체들을 필요에 따라 조립해 하나의 게임을 만드는 것이 좋겠다는 생각을 했습니다.
'C#' 카테고리의 다른 글
C# List, ArrayList, Dictionary (0) | 2024.03.19 |
---|---|
Unity Interface (0) | 2024.02.01 |
C# SnakeGame (1) | 2024.01.06 |
C# virtual, override (1) | 2024.01.05 |
C# Partial (2) | 2024.01.05 |