3-1 스네이크

class Program
{
    static void Main(string[] args)
    {
        // 게임 속도를 조정하기 위한 변수입니다. 숫자가 클수록 게임이 느려집니다.
        int gameSpeed = 100;
        int foodCount = 0; // 먹은 음식 수

        // 게임을 시작할 때 벽을 그립니다.
        DrawWalls();

        // 뱀의 초기 위치와 방향을 설정하고, 그립니다.
        Point p = new Point(4, 5, '*');
        Snake snake = new Snake(p, 4, Direction.RIGHT);
        snake.Draw();

        // 음식의 위치를 무작위로 생성하고, 그립니다.
        FoodCreator foodCreator = new FoodCreator(80, 20, '$');
        Point food = foodCreator.CreateFood();
        food.Draw();

        // 게임 루프: 이 루프는 게임이 끝날 때까지 계속 실행됩니다.
        while (true)
        {
            // 키 입력이 있는 경우에만 방향을 변경합니다.
            if (Console.KeyAvailable)
            {
                var key = Console.ReadKey(true).Key;

                switch (key)
                {
                    case ConsoleKey.UpArrow:
                        snake.direction = Direction.UP;
                        break;
                    case ConsoleKey.DownArrow:
                        snake.direction = Direction.DOWN;
                        break;
                    case ConsoleKey.LeftArrow:
                        snake.direction = Direction.LEFT;
                        break;
                    case ConsoleKey.RightArrow:
                        snake.direction = Direction.RIGHT;
                        break;
                }
            }

            // 뱀이 음식을 먹었는지 확인합니다.
            if (snake.Eat(food))
            {
                foodCount++; // 먹은 음식 수를 증가
                food.Draw();

                // 뱀이 음식을 먹었다면, 새로운 음식을 만들고 그립니다.
                food = foodCreator.CreateFood();
                food.Draw();
                if (gameSpeed > 10) // 게임이 점점 빠르게
                {
                    gameSpeed -= 10;
                }
            }
            else
            {
                // 뱀이 음식을 먹지 않았다면, 그냥 이동합니다.
                snake.Move();
            }

            Thread.Sleep(gameSpeed);

            // 벽이나 자신의 몸에 부딪히면 게임을 끝냅니다.
            if (snake.IsHitTail() || snake.IsHitWall())
            {
                break;
            }

            Console.SetCursorPosition(0, 21); // 커서 위치 설정
            Console.WriteLine($"먹은 음식 수: {foodCount}"); // 먹은 음식 수 출력
        }

        WriteGameOver();  // 게임 오버 메시지를 출력합니다.
        Console.ReadLine();
    }

    static void WriteGameOver()
    {
        int xOffset = 25;
        int yOffset = 22;
        Console.SetCursorPosition(xOffset, yOffset++);
        WriteText("============================", xOffset, yOffset++);
        WriteText("         GAME OVER", xOffset, yOffset++);
        WriteText("============================", xOffset, yOffset++);
    }

    static void WriteText(string text, int xOffset, int yOffset)
    {
        Console.SetCursorPosition(xOffset, yOffset);
        Console.WriteLine(text);
    }

    // 벽 그리는 메서드
    static void DrawWalls()
    {
        // 상하 벽 그리기
        for (int i = 0; i < 80; i++)
        {
            Console.SetCursorPosition(i, 0);
            Console.Write("#");
            Console.SetCursorPosition(i, 20);
            Console.Write("#");
        }

        // 좌우 벽 그리기
        for (int i = 0; i < 20; i++)
        {
            Console.SetCursorPosition(0, i);
            Console.Write("#");
            Console.SetCursorPosition(80, i);
            Console.Write("#");
        }
    }
}

public class Point
{
    public int x { get; set; }
    public int y { get; set; }
    public char sym { get; set; }

    // Point 클래스 생성자
    public Point(int _x, int _y, char _sym)
    {
        x = _x;
        y = _y;
        sym = _sym;
    }

    // 점을 그리는 메서드
    public void Draw()
    {
        Console.SetCursorPosition(x, y);
        Console.Write(sym);
    }

    // 점을 지우는 메서드
    public void Clear()
    {
        sym = ' ';
        Draw();
    }

    // 두 점이 같은지 비교하는 메서드
    public bool IsHit(Point p)
    {
        return p.x == x && p.y == y;
    }
}
// 방향을 표현하는 열거형입니다.
public enum Direction
{
    LEFT,
    RIGHT,
    UP,
    DOWN
}

public class Snake
{
    public List<Point> body; // 뱀의 몸통을 리스트로 표현합니다.
    public Direction direction; // 뱀의 현재 방향을 저장합니다.

    public Snake(Point tail, int length, Direction _direction)
    {
        direction = _direction;
        body = new List<Point>();
        for (int i = 0; i < length; i++)
        {
            Point p = new Point(tail.x, tail.y, '*');
            body.Add(p);
            tail.x += 1;
        }
    }

    // 뱀을 그리는 메서드입니다.
    public void Draw()
    {
        foreach (Point p in body)
        {
            p.Draw();
        }
    }

    // 뱀이 음식을 먹었는지 판단하는 메서드입니다.
    public bool Eat(Point food)
    {
        Point head = GetNextPoint();
        if (head.IsHit(food))
        {
            food.sym = head.sym;
            body.Add(food);
            return true;
        }
        else
        {
            return false;
        }
    }

    // 뱀이 이동하는 메서드입니다.
    public void Move()
    {
        Point tail = body.First();
        body.Remove(tail);
        Point head = GetNextPoint();
        body.Add(head);

        tail.Clear();
        head.Draw();
    }

    // 다음에 이동할 위치를 반환하는 메서드입니다.
    public Point GetNextPoint()
    {
        Point head = body.Last();
        Point nextPoint = new Point(head.x, head.y, head.sym);
        switch (direction)
        {
            case Direction.LEFT:
                nextPoint.x -= 2;
                break;
            case Direction.RIGHT:
                nextPoint.x += 2;
                break;
            case Direction.UP:
                nextPoint.y -= 1;
                break;
            case Direction.DOWN:
                nextPoint.y += 1;
                break;
        }
        return nextPoint;
    }

    // 뱀이 자신의 몸에 부딪혔는지 확인하는 메서드입니다.
    public bool IsHitTail()
    {
        var head = body.Last();
        for (int i = 0; i < body.Count - 2; i++)
        {
            if (head.IsHit(body[i]))
                return true;
        }
        return false;
    }

    // 뱀이 벽에 부딪혔는지 확인하는 메서드입니다.
    public bool IsHitWall()
    {
        var head = body.Last();
        if (head.x <= 0 || head.x >= 80 || head.y <= 0 || head.y >= 20)
            return true;
        return false;
    }
}

public class FoodCreator
{
    int mapWidth;
    int mapHeight;
    char sym;

    Random random = new Random();

    public FoodCreator(int mapWidth, int mapHeight, char sym)
    {
        this.mapWidth = mapWidth;
        this.mapHeight = mapHeight;
        this.sym = sym;
    }

    // 무작위 위치에 음식을 생성하는 메서드입니다.
    public Point CreateFood()
    {
        int x = random.Next(2, mapWidth - 2);
        // x 좌표를 2단위로 맞추기 위해 짝수로 만듭니다.
        x = x % 2 == 1 ? x : x + 1;
        int y = random.Next(2, mapHeight - 2);
        return new Point(x, y, sym);
    }
}

3-2 블랙잭 만들기

using System;
using System.Collections.Generic;

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();
        }

        // 에이스가 있고 총점이 21점을 넘을 때, 에이스를 1점으로 취급
        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
{
    // 딜러는 총점이 17점 미만일 때 계속해서 카드를 뽑는다
    public void KeepDrawingCards(Deck deck)
    {
        while (Hand.GetTotalValue() < 17)
        {
            Card drawnCard = DrawCardFromDeck(deck);
            Console.WriteLine($"딜러는 '{drawnCard}'을(를) 뽑았습니다. 현재 총합은 {Hand.GetTotalValue()}점입니다.");
        }
    }
}

// 블랙잭 게임을 표현하는 클래스
public class Blackjack
{
    private Player player;
    private Dealer dealer;
    private Deck deck;

    public void PlayGame()
    {
        deck = new Deck();
        player = new Player();
        dealer = new Dealer();

        // 게임 시작, 플레이어와 딜러는 각각 두 장의 카드를 뽑는다
        for (int i = 0; i < 2; i++)
        {
            player.DrawCardFromDeck(deck);
            dealer.DrawCardFromDeck(deck);
        }

        Console.WriteLine("게임을 시작합니다!");
        Console.WriteLine($"플레이어의 초기 카드 합: {player.Hand.GetTotalValue()}");
        Console.WriteLine($"딜러의 초기 카드 합: {dealer.Hand.GetTotalValue()}");

        // 플레이어의 차례, 21점이 넘지 않는다면 계속해서 카드를 뽑을 수 있다
        while (player.Hand.GetTotalValue() < 21)
        {
            Console.Write("카드를 더 뽑으시겠습니까? (y/n): ");
            string input = Console.ReadLine();

            if (input.ToLower() == "y")
            {
                Card drawnCard = player.DrawCardFromDeck(deck);
                Console.WriteLine($"'{drawnCard}'을(를) 뽑았습니다. 현재 총합은 {player.Hand.GetTotalValue()}점입니다.");
            }
            else
            {
                break;
            }
        }

        // 딜러의 차례, 총합이 17점이 넘을 때까지 계속해서 카드를 뽑는다
        Console.WriteLine("딜러의 차례입니다.");
        dealer.KeepDrawingCards(deck);
        Console.WriteLine($"딜러의 총합은 {dealer.Hand.GetTotalValue()}점입니다.");

        // 승자 판정
        if (player.Hand.GetTotalValue() > 21)
        {
            Console.WriteLine("플레이어의 카드 합이 21점을 초과했습니다. 딜러의 승리입니다.");
        }
        else if (dealer.Hand.GetTotalValue() > 21)
        {
            Console.WriteLine("딜러의 카드 합이 21점을 초과했습니다. 플레이어의 승리입니다.");
        }
        else if (player.Hand.GetTotalValue() > dealer.Hand.GetTotalValue())
        {
            Console.WriteLine("플레이어의 카드 합이 더 높습니다. 플레이어의 승리입니다.");
        }
        else
        {
            Console.WriteLine("딜러의 카드 합이 더 높거나 같습니다. 딜러의 승리입니다.");
        }
    }
}

class Program
{
    static void Main(string[] args)
    {
        Blackjack game = new Blackjack();
        game.PlayGame();
    }
}