오늘은 스파르타 코딩 클럽 unity 게임 개발 과정 6일차!
월요일에 시작했지만 .. 지렁이 게임을 만든다고 날을 새버려 화요일이 되었다..
챕터3: 과제
3-1 스네이크
콘솔 기반의 간단한 뱀 게임을 구현하는 것입니다. 기본적인 뱀 게임의 동작 방식은 아래와 같습니다:
- 뱀은 매 턴마다 자신의 앞으로 이동합니다.
- 사용자는 방향키를 이용하여 뱀의 이동 방향을 제어할 수 있습니다.
- 뱀은 맵에 무작위로 생성되는 음식을 먹을 수 있습니다. 뱀이 음식을 먹으면 점수가 올라가고, 뱀의 길이가 늘어납니다.
- 뱀이 벽이나 자신의 몸에 부딪히면 게임이 끝나고 'Game Over' 메시지를 출력합니다.
요구사항:
- Snake 클래스를 만듭니다. 이 클래스는 뱀의 상태와 이동, 음식 먹기, 자신의 몸에 부딪혔는지 확인 등의 기능을 담당합니다.
- FoodCreator 클래스를 만듭니다. 이 클래스는 맵의 크기 내에서 무작위 위치에 음식을 생성하는 역할을 합니다.
- Main 함수에서 게임을 제어하는 코드를 작성합니다. 이 코드는 뱀의 이동, 음식 먹기, 게임 오버 조건 확인 등을 주기적으로 수행합니다.
- 필요에 따라 추가적인 함수나 클래스를 작성하여 게임을 완성합니다.
자유롭게 구성하셔도 되고, 아래의 코드를 참고 하셔도 괜찮습니다!
- 제공 코드
- 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)**와 같이 호출하면, 사용자로부터의 키 입력을 화면에 표시하지 않습니다. 이것은 게임에서 사용자의 입력을 처리할 때 화면에 키 입력이 표시되는 것을 방지하기 위한 것입니다.
- 이 메소드를 사용하여 사용자로부터의 방향 키 입력을 받아 뱀의 이동 방향을 변경하는 등의 처리를 할 수 있습니다.
- Thread.Sleep()
위의 내용을 따라 만들면 되는데
처음에는 쉽게 생각했다.
그런데 꽤 어려운 과제였다.
구글링을 해도 내가 원하는 결과가 안나온다.
나는 과제에서 원하는 결과물이 있을거라고 생각하고
최대한 제공해준 코드에 맞춰 사용해볼려고 노력했다.
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
}
오늘은 일단 자자 내일 설명해도 되잖아..