본문 바로가기

내일배움캠프_TIL

8월17일 TIL

블랙잭 게임 구현하기

제공 코드

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

        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 class Blackjack
{
    // 코드를 여기에 작성하세요
}

class Program
{
    static void Main(string[] args)
    {
        // 블랙잭 게임을 실행하세요
    }
}

열거형

사용자가 상수 값을 보기 쉽게 하기 위해 선언하는 사용자 지정 자료형

단순히 숫자를 쓴 것보다 의미가 있는 문자로 코드를 작성하기 때문에 가독성이 올라간다

public enum Suit { Hearts, Diamonds, Clubs, Spades }
public enum Rank { Two = 2, Three, Four, Five, Six, Seven, Eight, Nine, Ten, Jack, Queen, King, Ace }

카드의 모양과 숫자를 표시하는 열거형


Card 클래스

    public Suit Suit { get; private set; }
    public Rank Rank { get; private set; }

set을 private로 제한하여 외부로부터의 값 변경을 막음

public Card(Suit s, Rank r)
    {
        Suit = s;
        Rank = r;
    }

생성자에서 카드의 모양과 숫자를 지정

    public int GetValue()
    {
        if ((int)Rank <= 10) // 2~10 숫자카드
        {
            return (int)Rank;
        }
        else if ((int)Rank <= 13) // 킹,퀸,잭
        {
            return 10;
        }
        else //에이스
        {
            return 11;
        }
    }

각 카드의 숫자에 따라서 어떤 점수를 가지는지 결정한다

    public override string ToString()
    {
        return $"{Rank} of {Suit}";
    }

현재 카드의 모양과 숫자를 문자열로 반환한다

$ 기호를 사용하면 " " 안에도 {}를 사용하여 변수나 계산식 등을 넣어 출력할 수 있다


Deck 클래스

    private List<Card> cards;

    public Deck() //52장의 트럼프덱 생성
    {
        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();
    }

cards 리스트를 선언 후 열거형 안의 값을 순서대로 올라가면서 각각의 모양과 숫자를 가진 card 객체를 리스트 안에 추가한다

    public void Shuffle()
    {
        Random rand = new Random();

        for (int i = 0; i < cards.Count; i++)
        {
            int j = rand.Next(i, cards.Count); //i ~ cards.Count 범위 안에서 무작위로 j에 대입
            Card temp = cards[i];
            cards[i] = cards[j];
            cards[j] = temp;
        }
    }

Shuffle에서는 0부터 52 까지의 카드들을 순서대로 올라가면서 j에 무작위 카드를 대입하고 i번째의 카드와 교체한다

    public Card DrawCard()
    {
        Card card = cards[0]; //카드 덱에서 1번째 카드 복사
        cards.RemoveAt(0); //카드 덱에서 1번째 카드 제거
        return card;
    }

섞인 카드들을 DrawCard에서 인덱스0에 접근해 첫번째 카드를 복사하면서 제거한다.

DrawCard를 다시 호출 시 이전에 복사된 카드는 제거되어 다시 가져올 수 없다


Hand 클래스

    private List<Card> cards;

    public Hand()
    {
        cards = new List<Card>();
    }

    public void AddCard(Card card)
    {
        cards.Add(card);
    }

Card 리스트를 선언하고 AddCard 메서드에서 리스트에 전달받은 카드를 추가한다

    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) //버스트 시 에이스 1장을 1점으로 계산
        {
            total -= 10;
            aceCount--;
        }

        return total;
    }

뽑은 카드들의 점수의 총합과 에이스가 몇장인지 저장할 변수를 생성하고 카드리스트에서 에이스가 몇개인지 찾는다

총 점수가 21점을 넘어 버스트 발생 시 에이스 1장의 점수를 11점에서 1점으로 변경하는 것을 반복한다

그 후 총 점수를 반환한다

    public List<Card> GetCards()
    {
        return cards;
    }

아래 Main에서 딜러의 카드 리스트를 출력하기 위해 추가한 메서드


Player 클래스

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

플레이어가 뽑을 카드들을 저장할 hand를 선언하고 카드를 뽑는다

drawnCard에 뽑은 카드를 저장하고 카드 리스트에 drawnCard의 값을 추가한다

그 후 뽑은 카드를 반환한다


Dealer 클래스

public class Dealer : Player
{
    public void Play(Deck deck)
    {
        while (Hand.GetTotalValue() < 17) DrawCardFromDeck(deck);
    }
}

Player클래스를 상속하고 Play 메서드에서 딜러 카드의 총 합이 17점 이상이 될 때까지 카드를 뽑는다


Blackjack 클래스

    private Deck Deck;
    private Player Player;
    private Dealer Dealer;

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

Deck, Player, Dealer를 각각 선언한다

    public void StartGame()
    {
        Console.WriteLine("블랙잭 게임 시작");
        Dealer.Play(Deck);
        Card card1, card2;
        int currentScore;
        card1 = Player.DrawCardFromDeck(Deck);
        card2 = Player.DrawCardFromDeck(Deck);
        currentScore = Player.Hand.GetTotalValue();
        Console.WriteLine($"첫번째 카드 : {card1.ToString()}");
        Console.WriteLine($"두번째 카드 : {card2.ToString()}");
        Console.WriteLine($"현재 카드의 총 합 : {currentScore}");
    }

StartGame에서 Dealer의 카드를 세팅하고 플레이어가 뽑은 카드와 카드 점수의 총 합을 저장하고 출력한다


Program 클래스

class Program
{
    static bool isStay = false;

    static void Main()
    {
        Deck deck = new();
        Player player = new();
        Dealer dealer = new();
        Blackjack blackjack = new(deck, player, dealer);

        blackjack.StartGame();
        int dealerScore = dealer.Hand.GetTotalValue();

        while (!isStay)
        {
            DrawOrStay(player, deck);
        }

        Console.WriteLine("딜러의 패 공개");
        Console.WriteLine($"딜러의 패 공개");
        foreach (Card card in dealer.Hand.GetCards())
        {
            Console.WriteLine(card);
        }
        Console.WriteLine($"딜러 카드의 총 합 : {dealerScore}");

        if (player.Hand.GetTotalValue() > dealer.Hand.GetTotalValue()
            || dealer.Hand.GetTotalValue() > 21)
            Console.WriteLine("플레이어 승");
        else if (player.Hand.GetTotalValue() < dealer.Hand.GetTotalValue()
            || dealer.Hand.GetTotalValue() <= 21)
            Console.WriteLine("딜러 승");
        else
            Console.WriteLine("무승부");
    }
    static void DrawOrStay(Player player, Deck deck)
    {
        Console.WriteLine("카드를 뽑습니까?\n뽑는다 : 1\n유지한다 : 2");
        string isDraw = Console.ReadLine();

        if (int.Parse(isDraw) == 1)
        {
            Card card = player.DrawCardFromDeck(deck);
            int currentScore = player.Hand.GetTotalValue();
            Console.WriteLine($"뽑은 카드 : {card}");
            Console.WriteLine($"현재 카드의 총 합 : {currentScore}");
            if (currentScore > 21)
            {
                Console.WriteLine("버스트");
                Console.WriteLine("패배하였습니다");
                Environment.Exit(0); // 버스트 시 콘솔 종료
            }
        }
        else if (int.Parse(isDraw) == 2)
        {
            isStay = true;
        }
        else Console.WriteLine("잘못된 값 입력. 1과 2 중 하나를 입력하세요");
    }
}

Main에서 객체들을 선언한다

isStay에서는 카드를 뽑는 행위를 반복할 while에 사용될 값을 저장한다

StartGame 이후에 딜러의 총 점수를 dealerScore에 저장한다

DrawOrStay는 플레이어와 덱을 매개변수로 전달받아 플레이어가 카드를 뽑는것을 수행한다

입력값은 1번이 드로우 2번이 유지하는 것으로 설정하고 카드를 뽑을 때마다 뽑은 카드와 갱신된 점수가 출력된다

만약 카드를 뽑아 21이 넘어 버스트가 나면 딜러의 패를 공개하지 않고 바로 패배한다

2번을 누르면 Main의 while 조건이 거짓으로 바뀌어 딜러의 패를 공개하고 승패 판정을 내린다


뱀 게임 구현하기

 

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

Main 메서드

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

게임 속도와 먹은 음식 수, 뱀의 초기 길이와 방향을 설정하고 벽을 그린다

foodCreator로 무작위 위치에 음식을 생성하고 그린다

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

뱀이 음식을 먹었는지 체크한다

먹었다면 foodCount를 증가시키고 새로운 먹이 생성 및 그리기를 진행한다

음식을 먹을때마다 게임 속도를 점점 증가시킨다

음식을 먹지 않았다면 그냥 넘어간다

            Thread.Sleep(gameSpeed);

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

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

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

게임속도 조절을 위해 Thread.Sleep으로 일시정지한다

벽이나 꼬리에 부딪히면 게임을 종료한다

그려진 벽 아래에 현재까지 먹은 음식 수를 출력한다

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

20 × 80 크기의 사각형을 그린다

사각형은 게임 맵의 벽이 된다


Point 클래스

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
}

뱀의 진행 방향을 표현하는 열거형이다


Snake 클래스

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

Snake객체 생성시 전달받은 값을 바탕으로 방향, 길이를 설정한다

    // 뱀을 그리는 메서드입니다.
    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;
    }

뱀의 충돌 여부를 확인하고 게임을 종료시킨다

종료 코드는 Main에서 작동한다


FoodCreator

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

맵의 전체 길이와 높이를 전달받는다

전달받은 맵의 범위 안에서 Random을 사용해 무작위 위치에 음식을 생성한다

'내일배움캠프_TIL' 카테고리의 다른 글

8월 21일 TIL  (0) 2023.08.22
8월 18일 TIL  (0) 2023.08.18
8월 16일 TIL  (0) 2023.08.16
8월 14일 TIL  (0) 2023.08.14
8월11일 TIL  (0) 2023.08.11