<aside>
💡 Notion 팁: 새 페이지를 만들고 템플릿 목록에서 데일리 일기
를 선택해 매일 아래 양식을 자동으로 생성할 수 있어요.
</aside>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
public class Point
{
public int x { get; set; }
public int y { get; set; }
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 class Snake
{
private List<Point> body;
private Direction direction;
public Snake(Point tail, int length, Direction _direction)
{
body = new List<Point>();
direction = _direction;
for (int i = 0; i < length; i++)
{
Point p = new Point(tail.x + i, tail.y, '*');
body.Add(p);
}
}
public void Move()
{
Point tail = body.Last();
Point head = GetNextPoint();
body.Insert(0, head);
body.RemoveAt(body.Count - 1);
}
public Point GetNextPoint()
{
Point head = body.First();
Point nextPoint = new Point(head.x, head.y, head.sym);
nextPoint.Move(direction);
return nextPoint;
}
public void HandleKey(ConsoleKey key)
{
if (key == ConsoleKey.LeftArrow && direction != Direction.RIGHT)
direction = Direction.LEFT;
else if (key == ConsoleKey.RightArrow && direction != Direction.LEFT)
direction = Direction.RIGHT;
else if (key == ConsoleKey.UpArrow && direction != Direction.DOWN)
direction = Direction.UP;
else if (key == ConsoleKey.DownArrow && direction != Direction.UP)
direction = Direction.DOWN;
}
public void Draw()
{
foreach (Point p in body)
{
p.Draw();
}
}
public void Move(Direction direction)
{
// 방향에 따라 x 또는 y 좌표를 조정하여 이동
if (direction == Direction.LEFT)
x--;
else if (direction == Direction.RIGHT)
x++;
else if (direction == Direction.UP)
y--;
else if (direction == Direction.DOWN)
y++;
}
}
public enum Direction
{
LEFT,
RIGHT,
UP,
DOWN
}
class Program
{
static void Main()
{
Console.SetWindowSize(80, 25);
Console.SetBufferSize(80, 25);
Point tail = new Point(4, 5, '*');
Snake snake = new Snake(tail, 4, Direction.RIGHT);
while (true)
{
if (Console.KeyAvailable)
{
ConsoleKeyInfo key = Console.ReadKey();
snake.HandleKey(key.Key);
}
snake.Move();
Console.Clear();
snake.Draw();
Thread.Sleep(100);
}
}
}
우선 먹이를 먹는 건 제쳐두고 뱀이 키보드 방향 키 입력을 받으면 콘솔 창에서 움직이도록 해보았다. 이 코드대로 하면 뱀이 잘 움직이는데, 콘솔 화면 밖으로 나갔을 때 OutOfRangeException이 발생하여 예외처리가 필요한 것과, 뱀의 속도가 너무 빨라 Thread.Sleep(); 값을 100보다 크게 설정해야 할 것 같다.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
public class Point
{
...
public bool IsHitWall(int maxX, int maxY)
{
return x <= 0 || x >= maxX || y <= 0 || y >= maxY;
}
}
public class Snake
{
private List<Point> body;
private Direction direction;
private int maxX;
private int maxY;
public Snake(Point tail, int length, Direction _direction, int _maxX, int _maxY)
{
body = new List<Point>();
direction = _direction;
maxX = _maxX;
maxY = _maxY;
for (int i = 0; i < length; i++)
{
Point p = new Point(tail.x + i, tail.y, '*');
body.Add(p);
}
}
...
public bool IsGameOver()
{
return body.Any(p => p.IsHitWall(maxX, maxY));
}
}
public enum Direction
{
LEFT,
RIGHT,
UP,
DOWN
}
class Program
{
static void Main()
{
Console.SetWindowSize(80, 25);
Console.SetBufferSize(80, 25);
Point tail = new Point(4, 5, '*');
int maxX = Console.WindowWidth;
int maxY = Console.WindowHeight;
Snake snake = new Snake(tail, 4, Direction.RIGHT, maxX, maxY);
while (true)
{
...
Console.Clear();
snake.Draw();
Thread.Sleep(300); // 이동 속도 조절을 위해 100보다 작은 값으로 수정 가능
}
}
}
다음과 같이 수정하여 뱀의 속도를 조절하고 뱀이 콘솔창 외곽(벽)에 닿았을 때 게임오버 되도록 했다.
이제 남은 건 먹이 구현이다.
public class Snake
{
...
public bool Eat(Point food)
{
Point head = GetNextPoint();
if (head.IsHit(food))
{
food.Clear();
food = null;
return true;
}
return false;
}
}
public class FoodCreator
{
private int mapWidth;
private int mapHeight;
private char sym;
private 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(1, 81); // X 좌표 범위를 1부터 80까지로
int y = random.Next(1, 21); // Y 좌표 범위를 1부터 20까지로
return new Point(x, y, sym);
}
}
...
class Program
{
static void Main()
{
...
FoodCreator foodCreator = new FoodCreator(80, 20, '$');
Point food = foodCreator.CreateFood();
food.Draw();
while (true)
{
...
if (snake.Eat(food))
{
food = foodCreator.CreateFood();
food.Draw();
}
...
food.Draw();
...
}
}
}
위의 코드를 추가하여 (80, 20)의 범위 내에서 먹이가 $ 표시로 랜덤하게 생성되도록 하고, 뱀이 먹이를 먹으면 먹이가 없어지고 다른 곳에 생성되도록 했다. (생각보다 뱀이 가늘어서 먹이 먹기가 쉽지않다 🐍)
다음으로는 먹은 먹이의 수를 콘솔 창에 표시하려고 했는데,
public class Snake
{
private List<Point> body;
private Direction direction;
private int maxX;
private int maxY;
int foodCount = 0;
...
public void IncreaseFoodCount()
{
foodCount++;
}
public int GetFoodCount()
{
return foodCount;
}
}
...
class Program
{
static void Main()
{
...
while (true)
{
if (Console.KeyAvailable)
{
ConsoleKeyInfo key = Console.ReadKey();
snake.HandleKey(key.Key);
}
Console.SetCursorPosition(0, 0);
Console.Write("먹은 음식의 수 : " + snake.GetFoodCount());
snake.Move();
if (snake.Eat(food))
{
snake.IncreaseFoodCount();
food = foodCreator.CreateFood();
food.Draw();
}
if (snake.IsGameOver())
{
Console.Clear();
Console.SetCursorPosition(35, 12);
Console.Write("Game Over");
break;
}
Console.Clear();
snake.Draw();
food.Draw();
Thread.Sleep(300); // 이동 속도 조절을 위해 100보다 작은 값으로 수정 가능
}
}
}
이렇게 했는데도 먹은 음식의 수가 콘솔 창에 출력되지 않았다.