먹이 추가(먹이를 먹으면 길이+1), 종료조건을 추가하면 완성된다
6. 먹이 추가
static int food_x, food_y; //food의 좌표값을 저장
const string sign_Food = "☆"; // 먹이
static int length; // 길이
길이는 먹을 때마다 1씩 올라간다
먹이 배치
// 랜덤위치에 음식 추가
static void Food()
{
bool food_crush_on = false; // food가 뱀 몸통 좌표에 생길 경우 true
Console.WriteLine($" Score : {score} Last Score : {last_score} Best Score : {best_score}");
Random rand = new Random();
while (true)
{
food_crush_on = false;
food_x = rand.Next(1, MAP_XSIZE - 1); // 난수를 좌표값에 넣음
food_y = rand.Next(1, MAP_YSIZE - 1);
for (int i = 0; i < length; i++) // food가 뱀 몸통과 겹치는지 확인
{
if (food_x == x[i] && food_y == y[i])
{
food_crush_on = true; // 겹치면 food_crush_on을 true로 설정
break;
}
}
if (food_crush_on)
{
continue; // 겹쳤을 경우 while문을 다시 시작
}
PrintTo(MAP_X + food_x, MAP_Y + food_y, sign_Food); // 안 겹쳤을 경우 좌표값에 food를 찍고
speed = Math.Max(50, speed - 3); // 속도 증가 (최소 50 이하로 내려가지 않도록)
break;
}
}
점수 추가
static int score; //점수 저장: reset함수에 의해 초기화됨
static int best_score = 0; //최고 점수 저장: reset함수에 의해 초기화 되지 않음
static int last_score = 0; //마지막 점수 저장: reset함수에 의해 초기화 되지 않음
7. 게임 종료조건(벽과 충돌, 몸통과 충돌)
게임종료
static void GameOver()
{
PrintTo(MAP_X + (MAP_XSIZE / 2) - 6, MAP_Y + 5, "+----------------------+");
PrintTo(MAP_X + (MAP_XSIZE / 2) - 6, MAP_Y + 6, " GAME OVER ");
PrintTo(MAP_X + (MAP_XSIZE / 2) - 6, MAP_Y + 7, "+----------------------+");
PrintTo(MAP_X + (MAP_XSIZE / 2) - 6, MAP_Y + 8, $" YOUR SCORE : {score}");
if (score > best_score)
{
best_score = score;
PrintTo(MAP_X + (MAP_XSIZE / 2) - 4, MAP_Y + 10, " BEST SCORE ");
}
Thread.Sleep(500);
Console.ReadKey(true);
Title();
}
Move에 종료조건을 추가
몸통과 머리를 1칸씩 옮긴다
// 이동
static void Move(int dir)
{
// 먹이
if (x[0] == food_x && y[0] == food_y)
{
score += 10;
Food();
length++;
x[length - 1] = x[length - 2];
y[length - 1] = y[length - 2];
}
// 벽과 충돌
if (x[0] == 0 || x[0] == MAP_XSIZE - 1 || y[0] == 0 || y[0] == MAP_YSIZE - 1)
{
GameOver();
return;
}
// 몸통과 충돌
for (int i = 1; i < length; i++)
{
if (x[0] == x[i] && y[0] == y[i])
{
GameOver();
return;
}
}
// 충돌하지 않았다면
// 몸통부터 1칸씩 옮긴다
PrintTo(MAP_X + x[length - 1], MAP_Y + y[length - 1], " "); // 몸통 마지막을 지움
for (int i = length - 1; i > 0; i--) /// 몸통 좌표를 한칸씩 옮김
{
x[i] = x[i - 1];
y[i] = y[i - 1];
}
PrintTo(MAP_X + x[0], MAP_Y + y[0], sign_Body); /// 머리가 있던 곳을 몸통으로 고침
// 머리를 1칸 옮긴다
/// 기본 방향은 왼쪽으로 설정되어있다
if (dir == (int)ConsoleKey.LeftArrow) --x[0]; // 방향에 따라 새로운 머리좌표(x[0], y[0])값을 변경
if (dir == (int)ConsoleKey.RightArrow) ++x[0];
if (dir == (int)ConsoleKey.UpArrow) --y[0];
if (dir == (int)ConsoleKey.DownArrow) ++y[0];
PrintTo(MAP_X + x[0], MAP_Y + y[0], sign_Head); // 새로운 머리좌표값에 머리를 그림
}
이 상태로 실행하면, 점수메세지가 Food에서 생성되는 문제가 있다
화면 아래쪽 벽의 아래에 점수가 표시되면 좋겠다
static void Food()
{
bool food_crush_on = false; // food가 뱀 몸통 좌표에 생길 경우 true
PrintTo(MAP_X, MAP_Y + MAP_YSIZE, " "); //점수표시
Console.WriteLine($" Score : {score} Last Score : {last_score} Best Score : {best_score}");
이젠 화면 아래에 생긴다
일시정지 기능 추가하고 끝내면 될 듯
일시정지 추가
static void Pause()
{
while (true)
{
if (key == (int)ConsoleKey.P)
{
PrintTo(MAP_X + (MAP_XSIZE / 2) - 9, MAP_Y, "< PAUSE : PRESS ANY KEY TO RESUME > ");
Thread.Sleep(400);
PrintTo(MAP_X + (MAP_XSIZE / 2) - 9, MAP_Y, " ");
Thread.Sleep(400);
}
else
{
// 아무 키나 누르면 다시 게임이 재개된다
DrawMap();
return;
}
if (Console.KeyAvailable)
{
key = (int)Console.ReadKey(true).Key;
}
}
}
메인메서드에 일시정지 추가하면 끝
static void Main(string[] args)
{
Title();
while (true)
{
if (Console.KeyAvailable) // 키 입력 버퍼에 키 입력을 받으면 true, 아무 입력이 없으면 false
{
ConsoleKeyInfo keyInfo = Console.ReadKey(true); // true: 입력된 키를 화면에 표시하지 않음,
// .Key: 어떤 키가 눌렸는지 반환된다(왼쪽 화살표 누르면 ConsoleKey.LeftArrow 반환)
key = (int)keyInfo.Key;
}
Thread.Sleep(speed);
switch (key)
{
case (int)ConsoleKey.LeftArrow:
if (dir != (int)ConsoleKey.RightArrow) dir = (int)ConsoleKey.LeftArrow;
break;
case (int)ConsoleKey.RightArrow:
if (dir != (int)ConsoleKey.LeftArrow) dir = (int)ConsoleKey.RightArrow;
break;
case (int)ConsoleKey.UpArrow:
if (dir != (int)ConsoleKey.DownArrow) dir = (int)ConsoleKey.UpArrow;
break;
case (int)ConsoleKey.DownArrow:
if (dir != (int)ConsoleKey.UpArrow) dir = (int)ConsoleKey.DownArrow;
break;
case (int)ConsoleKey.Escape:
Environment.Exit(0);
break;
case (int)ConsoleKey.P: // 'P' 키를 눌렀을 때 (일시정지)
Pause();
break;
}
key = 0; // 입력된 키 값을 초기화
Move(dir);
}
}
확인해보자
'유니티 부트캠프 8기 > Ch02. 프로그래밍 기초(C#)' 카테고리의 다른 글
3주차 과제1. 스네이크 게임2. 맵 만들기, 몸통 추가 (0) | 2025.02.16 |
---|---|
3주차 과제1. 스네이크 게임1. 프로토 타입 만들기 (0) | 2025.02.16 |
Console.KeyAvailable() (0) | 2025.02.08 |
디버깅 심화: 직접 실행창 사용하기 (0) | 2025.02.07 |
문자열의 저장방식 (0) | 2025.02.07 |