티스토리 뷰

제작한 작품 목록

  • 자잘한 게임 및 코드들(숫자 맞추기, 계산기 등등)
  • 틱택토
  • 스네이크 게임
  • 블랙잭 [기본적인 룰(스플릿 제외) 만 적용]

 

틱택토

[URL: https://lsu0503.tistory.com/53]

 

Today I Learned - Day 6 [틱택토 제작하기]

금일은 C#의 기본 문법에 대해서 공부하였습니다. 얼마 전 문법 톺아보기로도 한번 접했기도 한 지라, 전체적으로 복습한다는 느낌에 추가로 스파게티 코드 예방을 위해 '쉽게 알아볼 수 있게끔

lsu0503.tistory.com

해당 게임은 예외적으로 TIL로 작성되어 있습니다.

 

스네이크 게임

코드 전문

더보기

 

using System;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Reflection;

namespace _3rdWeekHomwork
{
    class Coordinate
    {
        public int x, y;

        public Coordinate(int _x, int _y)
        {
            x = _x;
            y = _y;
        }

        static public bool CompareCoordinate(Coordinate firstCoordinate, Coordinate secondCoordinate)
        {
            bool result = true;

            if(!(firstCoordinate.x == secondCoordinate.x))
                result = false;

            if (!(firstCoordinate.y == secondCoordinate.y))
                result = false;

            return result;
        }
    }

    class GameManager
    {
        private static GameManager instance;
        Field field;
        Snake snake;
        Thread gameUpdater;

        public GameManager()
        {
            field = new Field();
            snake = new Snake(field.fieldSize / 2, field.fieldSize / 2, field);
        }

        public static GameManager Instance()
        {
            if (instance == null)
                instance = new GameManager();

            return instance;
        }

        public void GameStart()
        {
            gameUpdater = new Thread(() => GameUpdater());
            gameUpdater.Start();

            getInput();
        }

        public void GameUpdater()
        {
            while (true)
            {
                Thread.Sleep(200);
                Update();
            }
        }

        public void getInput()
        {
            ConsoleKeyInfo input;

            while (true)
            {
                input = Console.ReadKey();

                switch (input.Key)
                {
                    case ConsoleKey.RightArrow:
                        snake.ChangeDirection(0);
                        break;
                    case ConsoleKey.UpArrow:
                        snake.ChangeDirection(1);
                        break;
                    case ConsoleKey.LeftArrow:
                        snake.ChangeDirection(2);
                        break;
                    case ConsoleKey.DownArrow:
                        snake.ChangeDirection(3);
                        break;
                    case ConsoleKey.Escape:
                        GameOver();
                        break;
                }
            }
        }

        void Update()
        {
            Console.SetCursorPosition(0, 0);
            snake.Update();
            UpdateDisplay();
        }

        void UpdateDisplay()
        {
            bool isExist;

            Console.Clear();
            for (int j = field.fieldSize; j >= -1; j--)
            {
                for (int i = -1; i <= field.fieldSize; i++)
                {
                    isExist = false;
                    Coordinate temp = new Coordinate(i, j);

                    if(i == -1 || i == field.fieldSize || j == -1 || j == field.fieldSize)
                    {
                        Console.Write("■");
                        isExist = true;
                    }

                    for (int k = 0; k < field.foodList.Count; k++)
                        if (Coordinate.CompareCoordinate(temp, field.foodList[k]))
                        {
                            Console.Write("★");
                            isExist = true;
                            break;
                        }

                    if (Coordinate.CompareCoordinate(temp, snake.snakeHead) && !isExist)
                    {
                        switch (snake.direction)
                        {
                            case 1:
                                Console.Write("▲");
                                break;
                            case 2:
                                Console.Write("◀");
                                break;
                            case 3:
                                Console.Write("▼");
                                break;
                            default:
                                Console.Write("▶");
                                break;
                        }

                        isExist = true;
                    }

                    for (int k = 0; k < snake.snakeBody.Count; k++)
                        if (Coordinate.CompareCoordinate(temp, snake.snakeBody[k]))
                        {
                            Console.Write("●");
                            isExist = true;
                            break;
                        }

                    if (!isExist)
                        Console.Write("  ");
                }

                Console.WriteLine();
            }
        }

        public void GameOver()
        {
            Console.WriteLine("Game Over");
            Console.WriteLine($"Score: {snake.snakeBody.Count}\n");
            Environment.Exit(0);
        }
    }

    class Field
    {
        public int fieldSize = 25;
        public List<Coordinate> foodList = new List<Coordinate>();

        public Field()
        {
            foodList.Clear();

            Coordinate temp = new Coordinate(new Random().Next(0, fieldSize), new Random().Next(0, fieldSize));

            while(temp.x == fieldSize / 2 && temp.y == fieldSize / 2)
                temp = new Coordinate(new Random().Next(0, fieldSize), new Random().Next(0, fieldSize));
            
            CreateFood(temp.x, temp.y);
        }

        public bool CreateFood(int x, int y)
        {
            Coordinate temp = new Coordinate(x, y);
            bool isExist = false;

            for(int i = 0; i < foodList.Count; i++)
                if(Coordinate.CompareCoordinate(temp, foodList[i]))
                    isExist = true;

            if (!isExist)
            {
                foodList.Add(temp);
                return true;
            }
            else
                return false;
        }
    }

    class Snake
    {
        Field field { get; set; }
        public Coordinate snakeHead = new Coordinate(0, 0);
        public List<Coordinate> snakeBody = new List<Coordinate>();
        public int direction = 0;
        int[] dx = { 1, 0, -1, 0 };
        int[] dy = { 0, 1, 0, -1 };

        public Snake(int x, int y, Field _field)
        {
            snakeHead = new Coordinate(x, y);
            snakeBody.Clear();

            field = _field;
        }

        public void ChangeDirection(int _direction)
        {
            if (MathF.Abs(direction - _direction) == 2 && snakeBody.Count > 0)
                GameManager.Instance().GameOver();
            else
                direction = _direction;
        }

        public void Update()
        {
            bool isGameOver = false;

            MoveSnake(dx[direction], dy[direction]);

            if (CheckCollision())
                isGameOver = true;
            if(CheckFieldOver())
                isGameOver = true;

            if(isGameOver)
                GameManager.Instance().GameOver();
        }

        public void MoveSnake(int distanceX, int distanceY)
        {
            snakeBody.Add(snakeHead);

            snakeHead = new Coordinate(snakeHead.x + distanceX, snakeHead.y + distanceY);

            bool isAte = false;

            for(int i = 0; i < field.foodList.Count; i++)
                if (Coordinate.CompareCoordinate(snakeHead, field.foodList[i]))
                {
                    isAte = true;

                    field.foodList.RemoveAt(i);

                    Coordinate temp;

                    while (true)
                    {
                        while (true)
                        {
                            bool tempBool1 = false;
                            temp = new Coordinate(new Random().Next(0, field.fieldSize), new Random().Next(0, field.fieldSize));

                            for (int j = 0; j < snakeBody.Count; j++)
                                if (Coordinate.CompareCoordinate(temp, snakeBody[j]))
                                    tempBool1 = true;

                            if (!tempBool1)
                                break;
                        }

                        bool tempBool2 = field.CreateFood(temp.x, temp.y);

                        if (tempBool2)
                            break;
                    }

                    break;
                }

            if (!isAte)
                snakeBody.RemoveAt(0);
        }

        public bool CheckCollision()
        {
            for(int i = 0; i < snakeBody.Count; i++)
                if(Coordinate.CompareCoordinate(snakeHead, snakeBody[i]))
                    return true;

            return false;
        }

        public bool CheckFieldOver()
        {
            if (snakeHead.x < 0 || snakeHead.y < 0 || snakeHead.x > field.fieldSize || snakeHead.y > field.fieldSize)
                return true;

            else
                return false;
        }
    }

    internal class Program
    {
        static void Main(string[] args)
        {
            GameManager.Instance().GameStart();
        }
    }
}

 

결과물

※ 콘솔창에는 XBOX Game Bar를 통한 녹화 기능을 사용할 수 없어서 스크린 샷으로 대체합니다.

※ 실수로 반대 방향키를 눌러서 게임 오버 된 상황입니다 [스크린샷 찍다가 방향 잘못봤네요.]

블랙잭

코드 전문

더보기
using System;

namespace _3rdWeekHomwork2
{
    struct Card
    {
        public int number;
        public char suit;

        public Card(int _number, char _suit)
        {
            number = _number;
            suit = _suit;
        }
    }

    class GameManager
    {
        private static GameManager instance;
        public Deck deck;
        public Board player;
        public Board dealer;

        public GameManager()
        {
            deck = new Deck(1);
            player = new Board();
            dealer = new Board();
        }

        public static GameManager Instance()
        {
            if (instance == null)
                instance = new GameManager();

            return instance;
        }

        public void StartGame()
        {
            player.DrawCard(deck.DrawCard());
            dealer.DrawCard(deck.DrawCard());
            player.DrawCard(deck.DrawCard());
            dealer.DrawCard(deck.DrawCard());

            Console.WriteLine("Dealer hand");
            dealer.DisplayHand();

            Console.WriteLine("Player hand");
            player.DisplayHand();

            CheckBoard();
        }

        public void DrawTurn(bool playerDraw)
        {
            bool dealerDraw = false;

            if(playerDraw)
                player.DrawCard(deck.DrawCard());

            if(dealer.total < 17)
            {
                dealer.DrawCard(deck.DrawCard());
                dealerDraw = true;
            }
            
            Console.WriteLine("Dealer hand");
            dealer.DisplayHand();

            Console.WriteLine("Player hand");
            player.DisplayHand();

            if (!playerDraw && !dealerDraw)
                GameOver(true);

            CheckBoard();
        }

        public void CheckBoard()
        {
            if (player.total == 21)
                GameOver(true);

            else if (dealer.total == 21)
                GameOver(false);

            else if (player.total > 21)
                GameOver(false);

            else if (dealer.total > 21)
                GameOver(true);
        }

        public void GameOver(bool isPlayer)
        {
            if (isPlayer)
                Console.WriteLine("\nYou Win!\n");
            else
                Console.WriteLine("\nYou Lose...\n");

            Environment.Exit(0);
        }
    }

    class Board
    {
        List<Card> handList = new List<Card>();
        public int total;

        public Board()
        {
            handList.Clear();
            total = 0;
        }

        public void DrawCard(Card _card)
        {
            handList.Add(_card);
            total += _card.number;

            UpdateTotal();
        }

        public void UpdateTotal()
        {
            int AAmouint = 0;
            total = 0;

            for(int i = 0; i < handList.Count; i++)
            {
                if (handList[i].number == 1)
                    AAmouint++;

                else if (handList[i].number > 10)
                    total += 10;

                else
                    total += handList[i].number;
            }

            for(int i = 0; i < AAmouint; i++)
            {
                if (total + ((AAmouint - i) * 11) > 21)
                    total += 1;

                else
                    total += 11;
            }
        }

        public void DisplayHand()
        {
            Console.Write($"{handList[0].suit} {handList[0].number}");

            for (int i = 1; i < handList.Count; i++)
            {
                if(handList[i].number == 1)
                    Console.Write($" | {handList[i].suit} A");

                else if (handList[i].number == 11)
                    Console.Write($" | {handList[i].suit} J");

                else if (handList[i].number == 12)
                    Console.Write($" | {handList[i].suit} Q");

                else if (handList[i].number == 13)
                    Console.Write($" | {handList[i].suit} K");

                else
                    Console.Write($" | {handList[i].suit} {handList[i].number}");
            }

            Console.WriteLine($"\ntotal: {total}\n");
        }
    }

    class Deck
    {
        public List<Card> deckList = new List<Card>();

        public Deck(int numDeck)
        {
            List<Card> tempDeck = new List<Card>();

            for (int i = 0; i < numDeck; i++)
            {
                for(int j = 1; j <= 13; j++)
                {
                    tempDeck.Add(new Card(j, '♤'));
                    tempDeck.Add(new Card(j, '◆'));
                    tempDeck.Add(new Card(j, '♥'));
                    tempDeck.Add(new Card(j, '♧'));
                }
            }

            deckList = tempDeck.OrderBy(_ => new Random().Next()).ToList();
        }

        public Card DrawCard()
        {
            Card drawed = deckList[0];
            deckList.RemoveAt(0);
            return drawed;
        }
    }

    internal class Program
    {
        static void Main(string[] args)
        {
            string playerInput = null;

            GameManager.Instance().StartGame();

            while (true)
            {
                Console.Write("Draw Card? (Y/N): ");
                playerInput = Console.ReadLine();

                if(playerInput != "Y" && playerInput != "N")
                {
                    Console.WriteLine("Wrong Command!");
                    continue;
                }

                if (playerInput == "Y")
                    GameManager.Instance().DrawTurn(true);

                else if(playerInput == "N")
                    GameManager.Instance().DrawTurn(false);
            }
        }
    }
}

결과물

플레이어 버스트 패배

 

플레이어가 21에 더 가까워서 승리.

[딜러는 17 이상이라 드로우 불가 -> 양쪽 모두 드로우를 안했으므로 게임 종료]

 

정확히 21으로 플레이어 승리

 

 

마무리하며

Unity가 아닌 C# 기본 코딩 만으로 게임을 제작하는 감각이 신선했었습니다.

열심히 머리 굴려가면서 제작 다 했는데 알고 보니까 강의 자료에 과제 관련 정보가 있어서 허탈하기도 했지만...

 

아무래도 그래픽 관련해서도 제가 직접 코딩해야 하다 보니, 그 부분에서 조금 당황했던 감이 있습니다.

다만, 아무래도 콘솔창 자체적으로 한계가 있다 보니, 제작 자체는 수월하게 진행된 거 같습니다.

 

이제 금주의 과제인 TextRPG 제작이 남았는데, TextRPG의 기본 구성을 잘 몰라서 일단 자료 탐색 부터 해 봐야 할 거 같습니다. 충동적으로 만들었다가는 콘솔창에서 턴제 RPG를 하는 꼴이 될 거 같아서...;;

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/04   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30
글 보관함