스파르타코딩클럽 게임개발

오늘은 스파르타 코딩 클럽 unity 게임 개발 과정 6일차!

코드천자문 2023. 11. 7. 02:22
반응형

월요일에 시작했지만 .. 지렁이 게임을 만든다고 날을 새버려 화요일이 되었다..

 

챕터3: 과제

3-1 스네이크

콘솔 기반의 간단한 뱀 게임을 구현하는 것입니다. 기본적인 뱀 게임의 동작 방식은 아래와 같습니다:

  1. 뱀은 매 턴마다 자신의 앞으로 이동합니다.
  2. 사용자는 방향키를 이용하여 뱀의 이동 방향을 제어할 수 있습니다.
  3. 뱀은 맵에 무작위로 생성되는 음식을 먹을 수 있습니다. 뱀이 음식을 먹으면 점수가 올라가고, 뱀의 길이가 늘어납니다.
  4. 뱀이 벽이나 자신의 몸에 부딪히면 게임이 끝나고 'Game Over' 메시지를 출력합니다.

요구사항:

  1. Snake 클래스를 만듭니다. 이 클래스는 뱀의 상태와 이동, 음식 먹기, 자신의 몸에 부딪혔는지 확인 등의 기능을 담당합니다.
  2. FoodCreator 클래스를 만듭니다. 이 클래스는 맵의 크기 내에서 무작위 위치에 음식을 생성하는 역할을 합니다.
  3. Main 함수에서 게임을 제어하는 코드를 작성합니다. 이 코드는 뱀의 이동, 음식 먹기, 게임 오버 조건 확인 등을 주기적으로 수행합니다.
  4. 필요에 따라 추가적인 함수나 클래스를 작성하여 게임을 완성합니다.

자유롭게 구성하셔도 되고, 아래의 코드를 참고 하셔도 괜찮습니다!

  • 제공 코드
  • using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading;

    class Program
    {
        static void Main(string[] args)
        {
            // 뱀의 초기 위치와 방향을 설정하고, 그립니다.
            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)
            {
                // 키 입력이 있는 경우에만 방향을 변경합니다.
              
                // 뱀이 이동하고, 음식을 먹었는지, 벽이나 자신의 몸에 부딪혔는지 등을 확인하고 처리하는 로직을 작성하세요.
                // 이동, 음식 먹기, 충돌 처리 등의 로직을 완성하세요.
                
                Thread.Sleep(100); // 게임 속도 조절 (이 값을 변경하면 게임의 속도가 바뀝니다)

                // 뱀의 상태를 출력합니다 (예: 현재 길이, 먹은 음식의 수 등)
            }
        }
    }

    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
    }
  • 사용하게 될 함수
    • Thread.Sleep()
      • .NET에서 제공하는 Thread 클래스의 메소드 중 하나로, 특정 시간 동안 현재 실행 중인 스레드의 실행을 중지합니다.
      • 이 메소드의 매개변수로는 스레드가 일시 중지될 시간(밀리초 단위)를 전달합니다. 예를 들어, **Thread.Sleep(1000)**은 현재 스레드를 1초 동안 중지시킵니다.
      • 이 메소드를 사용하여 게임의 프레임 속도를 제어할 수 있습니다. Thread.Sleep() 메소드로 일정 시간을 기다리면, 그 시간 동안 다른 작업(예: 사용자 입력 처리, 뱀 이동 처리 등)을 수행할 수 있습니다.
    • Console.ReadKey()
      • .NET에서 제공하는 Console 클래스의 메소드 중 하나로, 사용자로부터 키보드 입력을 받아옵니다.
      • 이 메소드는 ConsoleKeyInfo 객체를 반환하며, 이 객체를 통해 어떤 키가 눌렸는지를 알 수 있습니다.
      • **Console.ReadKey(true)**와 같이 호출하면, 사용자로부터의 키 입력을 화면에 표시하지 않습니다. 이것은 게임에서 사용자의 입력을 처리할 때 화면에 키 입력이 표시되는 것을 방지하기 위한 것입니다.
      • 이 메소드를 사용하여 사용자로부터의 방향 키 입력을 받아 뱀의 이동 방향을 변경하는 등의 처리를 할 수 있습니다.

 

위의 내용을 따라 만들면 되는데 

 

처음에는 쉽게 생각했다.

 

그런데 꽤 어려운 과제였다.

 

구글링을 해도 내가 원하는 결과가 안나온다.

 

나는 과제에서 원하는 결과물이 있을거라고 생각하고 

 

최대한 제공해준 코드에 맞춰 사용해볼려고 노력했다.

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Xml.Linq;

class Program
{
        static void Main(string[] args)
        {

                // ConsoleKeyInfo를 사용해 더 쉽게 움직인다. 
                ConsoleKeyInfo consoleKeyInfo;
                // 뱀의 초기 위치와 방향을 설정하고, 그립니다.
                Point p = new Point(4, 5, '*');
                Snake snake = new Snake(p, 4, Direction.RIGHT);
                snake.Draw();

                // 음식의 위치를 무작위로 생성하고, 그립니다.
                FoodCreator foodCreator = new FoodCreator(5, 10, '$');
                Point food = foodCreator.CreateFood();
                food.Draw();
                //게임 판을 만든다 30*20
                gameDraw();

                // 게임 루프: 이 루프는 게임이 끝날 때까지 계속 실행됩니다.
                while (true)
                {
                        Console.SetCursorPosition(1, 21);
                        Console.WriteLine($"한계 위치는 X:0,30  Y:0,20");
                        Console.SetCursorPosition(5, 22);
                        Console.WriteLine($"나의 위치는 X:{snake.GetPoint().x} Y:{snake.GetPoint().y}");
                        Console.SetCursorPosition(5, 23);
                        Console.WriteLine($"내가 먹은 먹이수 :{snake.GetEitCount()}");
                        Console.SetCursorPosition(10, 24);
                        Console.WriteLine($"내 길이 :{snake.GetWidth()}");
                        consoleKeyInfo = Console.ReadKey();
                        //뱀과 푸드가 닿으면 길이가 늘어나고 다시 랜덤한 곳으로 먹이가 나옴
                        if (foodCreator.IsHit(snake.GetPoint()))
                        {
                                snake.Eit();
                                foodCreator.Rnadom();
                                foodCreator.Draw();
                        }
                        switch (consoleKeyInfo.Key)
                        {
                                case ConsoleKey.Enter:
                                        break;
                                case ConsoleKey.LeftArrow:
                                        snake.Clear();
                                        snake.Move(Direction.LEFT);
                                        snake.Draw();
                                        break;
                                case ConsoleKey.UpArrow:
                                        snake.Clear();
                                        snake.Move(Direction.UP);
                                        snake.Draw();
                                        break;
                                case ConsoleKey.RightArrow:
                                        snake.Clear();
                                        snake.Move(Direction.RIGHT);
                                        snake.Draw();
                                        break;
                                case ConsoleKey.DownArrow:
                                        snake.Clear();
                                        snake.Move(Direction.DOWN);
                                        snake.Draw();
                                        break;
                                default:
                                        break;
                        }
                        //패배 조건
                        if (snake.IsHit(snake.GetPoint()) || snake.Lose())
                        {
                                break;
                        }

                        // 뱀이 이동하고, 음식을 먹었는지, 벽이나 자신의 몸에 부딪혔는지 등을 확인하고 처리하는 로직을 작성하세요.
                        // 이동, 음식 먹기, 충돌 처리 등의 로직을 완성하세요.

                        //Thread.Sleep(100); // 게임 속도 조절 (이 값을 변경하면 게임의 속도가 바뀝니다)


                }
                Console.WriteLine("너 졌음ㅋㅋ");
        }

        private static void gameDraw()
        {
                int x = 0;
                int y = 0;

                for (int j = 0; j < 2; j++)
                {
                        for (int i = 0; i < 30; i++)
                        {
                                Console.SetCursorPosition(i, y);
                                Console.Write("-");
                        }
                        y = 20;
                }
                for (int j = 0; j < 2; j++)
                {
                        for (int i = 0; i < 25; i++)
                        {
                                Console.SetCursorPosition(x, i);
                                Console.Write("|");
                        }
                        x = 30;
                }
        }
}

public class FoodCreator
{
        Random random = new Random();
        int width;
        int height;
        char sym;

        public FoodCreator(int width, int height, char sym)
        {
                this.width = width;
                this.height = height;
                this.sym = sym;
        }
        public Point CreateFood()
        {
                return new Point(width, height, sym);
        }
        public void Rnadom()
        {
                width = random.Next(0, 20);
                height = random.Next(0,20);
        }
        public void Draw()
        {
                Console.SetCursorPosition(width, height);
                Console.Write(sym);
        }
        public bool IsHit(Point p)
        {
                return p.x == width && p.y == height;
        }
}
public class Snake
{
        List<int[]> body = new List<int[]>();
        Point point;
        int width;
        int eitCount = 0;
        Direction direction;
        public Snake(Point p, int width, Direction direction)
        {
                this.point = p;
                this.width = width;
                this.direction = direction;
                for (int i = 0; i < width; i++)
                {
                        Move(direction);
                        Draw();
                }
        }
        
        public bool Lose()
        {
                return GetPoint().x >= 30 || GetPoint().x <= 0 || GetPoint().y >= 20|| GetPoint().y <= 0;
        }
        public void Move(Direction direction)
        {
                switch (direction)
                {
                        case Direction.LEFT:
                                point.x--;
                                break;
                        case Direction.RIGHT:
                                point.x++;
                                break;
                        case Direction.UP:
                                point.y--;
                                break;
                        case Direction.DOWN:
                                point.y++;
                                break;
                        default:
                                break;
                }
                body.Add(new int[] { point.x, point.y });
        }
        //리스트에 제일 먼저 등록된 개체의 위치에 빈칸을 넣고 개체를 삭제
        public void Clear()
        {
                if (body.Count >= width)
                {
                        Console.SetCursorPosition(body.First()[0], body.First()[1]);
                        Console.Write(' ');
                        body.RemoveAt(0);
                }
        }

        public void Draw()
        {
                Console.SetCursorPosition(point.x, point.y);
                Console.Write(point.sym);
        }
        //머리의 위치와 몸통의 위치중 접촉이 생기는 것이 하나라도 있다면 트루
        public bool IsHit(Point p){ return body.Where(x => (p.x == x[0]) && (p.y == x[1])).Count() > 1; }
        //냠냠 허리 늘어남
        public void Eit() {
                eitCount++;
                width++;
        }
        public int GetWidth() { return width; }
        public int GetEitCount() { return eitCount; }
        public Point GetPoint() { return new Point(body.Last()[0], body.Last()[1], point.sym); }

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

오늘은 일단 자자 내일 설명해도 되잖아.. 

반응형