👾 내일배움캠프/🎮 TIL & WIL

내일배움캠프 (휴일) TIL - 블랙잭 C#

리리핸 2023. 8. 20. 23:59

수정 예정

 

using System;
using System.Collections.Generic;
using System.Numerics;

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 IReadOnlyList<Card> Cards => cards.AsReadOnly();

    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 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
{
    public void DealerTurn(Blackjack game, Player player)
    {
        Console.Clear();

        Console.WriteLine("==============================");
        Console.WriteLine("* 나의 합: " + player.Hand.GetTotalValue());
        Console.WriteLine();

        Console.WriteLine("* 딜러의 카드: ");
        foreach (Card c in Hand.Cards)
        {
            Console.WriteLine(c.ToString());
        }
        while (Hand.GetTotalValue() < 17)
        {
            DrawCardFromDeck(game.deck);
            Console.WriteLine(Hand.Cards[Hand.Cards.Count() - 1].ToString());
            Thread.Sleep(1000);
        }
        Console.WriteLine();

        Console.WriteLine("* 딜러의 합: " + Hand.GetTotalValue());
        Console.WriteLine("==============================");
        Console.WriteLine();

    }
}


public class Blackjack
{
    public Deck deck;

    public Blackjack(Player player, Dealer dealer)
    {
        deck = new Deck();
        StartGame(player, dealer);
    }


    public void StartGame(Player player, Dealer dealer)
    {
        dealer.DrawCardFromDeck(deck);
        dealer.DrawCardFromDeck(deck);

        player.DrawCardFromDeck(deck);
        player.DrawCardFromDeck(deck);

        Print(player, dealer);

        Console.WriteLine();
    }


    public void Print(Player player, Dealer dealer)
    {
        Console.WriteLine();
        Console.Clear();
        
        Console.WriteLine("==============================");

        Console.Write("* 딜러의 카드: ");
        Console.WriteLine(dealer.Hand.Cards[0]);
        Console.WriteLine();

        Console.WriteLine("* 나의 카드: ");
        foreach (Card c in player.Hand.Cards)
        {
            Console.WriteLine(c.ToString());
        }
        Console.WriteLine();

        Console.WriteLine("* 나의 합: " + player.Hand.GetTotalValue());

        Console.WriteLine("==============================");

        Console.WriteLine();
    }

}


class Program
{

    static int winner;
    static bool isRunning = true;


    static void Main(string[] args)    // 플레이어와 딜러를 블랙잭에서 객체화 게 나을지 고민해보기
    {

        Player player = new Player();
        Dealer dealer = new Dealer();

        Blackjack game = new Blackjack(player, dealer);

        if (player.Hand.GetTotalValue() == 21)
        {
            winner = 4;
            GameEnd();
        }

        while (isRunning)
        {
            Console.WriteLine("Hit(h) or Stay(s)? : ");
            string input = Console.ReadLine();
            Console.WriteLine("                      ");


            // 유효하지 않은 값 입력시 입력받기 반복

            while (input != "h" && input != "s")
            {
                Console.WriteLine("잘못된 값을 입력하셨습니다.");
                Console.WriteLine();
                Console.WriteLine("Hit(h) or Stay(s)? : ");
                input = Console.ReadLine();
                Console.WriteLine();
            }

            //------------------------------

            if (input == "h")
            {
                player.DrawCardFromDeck(game.deck);
                game.Print(player, dealer);
            }
            else
            {
                dealer.DealerTurn(game, player);

                // 카드 합 비교

                Check(player, dealer);
                if (!isRunning) continue;

                if (player.Hand.GetTotalValue() > dealer.Hand.GetTotalValue()) winner = 2;
                else if (player.Hand.GetTotalValue() == dealer.Hand.GetTotalValue()) winner = 3;
                else winner = 1;

                //-----------------------------

                GameEnd();
                continue;
       
            }

            Check(player, dealer);
        }

    }


    public static void GameEnd()
    {
        Thread.Sleep(1000);

        isRunning = false;
        switch (winner)
        {
            case 1:
                Console.WriteLine("******************************");
                Console.WriteLine("******************************");
                Console.WriteLine("********* GAME  OVER *********");
                Console.WriteLine("*********            *********");
                Console.WriteLine("********* YOU  LOSE! *********");
                Console.WriteLine("******************************");
                Console.WriteLine("******************************");
                break;
            case 2:
                Console.WriteLine("******************************");
                Console.WriteLine("******************************");
                Console.WriteLine("********* GAME  OVER *********");
                Console.WriteLine("*********            *********");
                Console.WriteLine("*********  YOU  WIN! *********");
                Console.WriteLine("******************************");
                Console.WriteLine("******************************");
                break;
            case 3:
                Console.WriteLine("******************************");
                Console.WriteLine("******************************");
                Console.WriteLine("********* GAME  OVER *********");
                Console.WriteLine("*********            *********");
                Console.WriteLine("*********   TIED!    *********");
                Console.WriteLine("******************************");
                Console.WriteLine("******************************");
                break;
            case 4:
                Console.WriteLine("******************************");
                Console.WriteLine("******************************");
                Console.WriteLine("*********    BLACK   *********");
                Console.WriteLine("*********            *********");
                Console.WriteLine("*********    JACK    *********");
                Console.WriteLine("******************************");
                Console.WriteLine("******************************");
                break;
        }

        Thread.Sleep(5000);
    }


    
    static void Check(Player player, Dealer dealer)
    {
        // 매 턴 플레이어 혹은 딜러의 카드 합이 21을 넘는지 확인
        if (player.Hand.GetTotalValue() > 21)
        {
            isRunning = false;
            winner = 1;
            GameEnd();
        }
        else if (dealer.Hand.GetTotalValue() > 21)
        {
            isRunning = false;
            winner = 2;
            GameEnd();
        }
    }
}