방명록
- C# #7 스네이크 게임2023년 08월 18일 13시 55분 00초에 업로드 된 글입니다.작성자: noun06
개요
3주차 과제 중 스네이크 게임이다. 초기 게임 구조 설계와 각 클래스별 생성자를 구현하는 부분은 완료하였지만 세부적인 메서드를 작성하는 것이 감이 잡히지 않아서 풀이 코드를 참조하면서 작업을 진행하였다. 그 후 모든 코드를 해석하고 이해하는 과정을 주석으로 남기는 것으로 마무리하였다.
설명
- Main 메서드: 프로그램의 시작점이다. 뱀과 음식의 생성, 게임 실행 및 초기화, 충돌체크, 게임 오버 등을 제어.
- DrawWalls 메서드: 게임의 벽을 그리는 역할.
- WriteGameover 메서드: 게임 오버 메시지를 출력.
- WriteText 메서드: 텍스트를 지정된 위치에 출력.
- 키 입력처리: Console.KeyAvaiable()을 통해 사용자의 키 입력 여부를 확인하고 Console.ReadKey()를 통해 실제 입력된 키를 읽음. 그 후 각 키 입력마다의 출력을 지정함.
- 게임 속도 조정: 매개변수로 일시 중지될 시간을 전달하며 작업의 일시적인 지연을 위해 사용되는 Thread.Sleep()메서드 사용. 'gameSpeed' 변수에 지정된 값만큼 게임을 일시적으로 멈추게 하여 뱀의 이동이 지정된 시간마다 이루어짐.
- Point 클래스: 좌표와 모양을 나타내는 point를 그리거나 지우는 것을 관리하는 역할.
- Direction 열거형(enum): 뱀의 방향을 정의하여 방향을 나타내기 위한 값 지정.
- Snake 클래스: 뱀의 상태와 동작을 관리, Move() 메서드를 통해 뱀의 이동 제어.
- FoodCreator 클래스: 음식의 생성과 위치를 관리.
- Point, Snake, FoodCreator 클래스에서 객체 초기화를 위해 생성자 사용.
코드
using System.Drawing; using System.Xml.Linq; 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; } // x 좌표 public int y { get; set; } // y 좌표 public char sym { get; set; } // 그려질 모양 // 생성자: 초기 좌표, 모양 설정 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 = x % 2 == 1 ? x : x + 1; // x 좌표를 2단위로 맞춤 int y = random.Next(2, mapHeight - 2); return new Point(x, y, sym); } }
게임 화면
'C#' 카테고리의 다른 글
C# #9 알고리즘 기초 2 (0) 2023.08.19 C# #8 TextRPG 1 (0) 2023.08.18 C# #6 알고리즘 기초 (0) 2023.08.17 C# #5 클래스, 객체, 상속, 다형성 (0) 2023.08.16 C# #4 메서드와 구조체 (0) 2023.08.15 다음글이 없습니다.이전글이 없습니다.댓글