[C#] Snake Game 만들기

고현규·2023년 11월 8일

GAME RULE

  1. 맵을 생성한다.
  2. 플레이어(뱀)을 스폰한다. 위치는 따로 지정해준다.
  3. 뱀은 매 시간마다 좌표를 이동한다. 방향키로 이동 방향을 정한다.
  4. 랜덤한 위치에 먹이가 스폰된다. 단, 뱀이 있는 공간과 벽에는 스폰하면 안된다.
  5. 먹이를 먹으면 뱀의 길이가 길어진다. 그리고 다시 스폰된다.
  6. 벽과 자신의 몸에 부딛히면 패배한다.

게임 룰을 정리했을 때 위와 같다.

구상한 로직

  • 머리의 좌표를 생성하고 해당 좌표를 방향키가 눌린 곳으로 더하고 뺀다.
    • 머리의 좌표를 다음 몸통에게 전달한다. 이를 몸의 길이만큼 반복한다.

  • 다음에 이동할 경로에 먹이가 있으면 머리의 좌표를 해당 먹이의 위치로 바꾼다.
    • 좌표를 옮긴 후, 몸의 길이를 늘린다.

  • 좌, 우 방향키를 입력하면 상, 하 방향키만 입력할 수 있다.
    마찬가지로 상, 하 방향키를 입력하면, 좌, 우 방향키만 입력할 수 있다.

  • 머리와 몸통이 있는 곳은 true로 전달해서 해당 위치는 몸으로 표시하여
    지나온 곳이 계속 몸통으로 표시되게 하지 않는다.

처음에는 모든 머리와 몸통의 배열의 행 열을 바꿔야 하나? 생각했는데
상하로 움직였을 때 뒤따라오는 몸통의 좌표를 바꾸기 어렵다는걸 알았다.

머리의 좌표를 뒤쪽의 몸통으로 계속 전달하면 뱀의 맨 뒤 꼬리를 삭제하는 일 없이
길이를 추가하는 작업만 진행하면 된다고 생각했다.

막혔던 부분

  • 좌표를(n, m)을 저장하는 방법
    • 클래스를 하나 만들어서 변수 두개에 x, y 좌표를 저장하여

  • 머리가 저장한 좌표를 다음 몸통으로 전달하는 방법
  • 맵과 뱀을 그릴 때 마다 방향키 입력이 되었는지 확인해야 되는가

문제 풀이를 보고 막혔던 부분을 어떻게 풀이했는지 살펴봤다.

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

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

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

배운 점과 느낀점.

클래스의 활용을 하는법이 익숙하지 않아 이렇게 좌표값으로 이용할 수도 있다는 것을 배웠다.
해당 Point 함수로 뱀과 먹이에 모두 사용할 수 있다는 점에도 공부가 많이 됐다.
방향키 입력이 있을 때만 방향 변수를 변경해주는 식으로 작성되어 있었고
풀이에서는 꼬리를 계속해서 지워주고 있었다.

꼬리를 지우는 방향이 아니라, 구상했던 뱀의 True, false의 형태는 어떤지 구현해보고 생각 해봐야겠다.

profile
게임 개발과 기획

0개의 댓글