문제
'Dummy' 라는 도스게임이 있다. 이 게임에는 뱀이 나와서 기어다니는데, 사과를 먹으면 뱀 길이가 늘어난다. 뱀이 이리저리 기어다니다가 벽 또는 자기자신의 몸과 부딪히면 게임이 끝난다.
게임은 NxN 정사각 보드위에서 진행되고, 몇몇 칸에는 사과가 놓여져 있다. 보드의 상하좌우 끝에 벽이 있다. 게임이 시작할때 뱀은 맨위 맨좌측에 위치하고 뱀의 길이는 1 이다. 뱀은 처음에 오른쪽을 향한다.
뱀은 매 초마다 이동을 하는데 다음과 같은 규칙을 따른다.
- 먼저 뱀은 몸길이를 늘려 머리를 다음칸에 위치시킨다.
- 만약 이동한 칸에 사과가 있다면, 그 칸에 있던 사과가 없어지고 꼬리는 움직이지 않는다.
- 만약 이동한 칸에 사과가 없다면, 몸길이를 줄여서 꼬리가 위치한 칸을 비워준다. 즉, 몸길이는 변하지 않는다.
사과의 위치와 뱀의 이동경로가 주어질 때 이 게임이 몇 초에 끝나는지 계산하라.
풀이
Deque 메소드를 이용해서 풀었다.
머리와 꼬리의 좌표를 Deque에 넣어주고 지워주는 방식을 사용하였다.
Deque 와 Queue 와 다른점은 앞과 뒤 모두에서 자료를 삭제 추가해줄 수 있는 점이다.
뱀의 방향은
dx = { 1, 0, -1, 0 }
dy = { 0, 1, 0, -1 } 으로 선언하여 사용 하였다.
순서대로 동, 남, 서, 북 으로 움직이는 방향이다.
snakeDir = (snakeDir + dir[timeIdx]) % 4;
총 인덱스가 4개이므로 방향을 전환 시켜줄때 현재의 방향에서 해당 값을 더해준뒤 mod 연산을 통해 방향을 지정했다.
//벽과 충돌하는 경우
if(nx <= 0 || nx > n || ny <= 0 || ny > n) {
System.out.println(second + 1);
break;
}
// 자신의 몸과 부딪히는 경우
if(map[nx][ny] == 2) {
System.out.println(second + 1);
break;
}
위의 두가지 경우가 나오면 그때의 시간을 출력한다.
if(map[nx][ny] == 1) {
//사과를 만난경우 꼬리를 남겨두고 머리를 추가한다.
map[nx][ny] = 2;
snake.addFirst(new point(nx, ny));
}
else if(map[nx][ny] == 0) {
//사과를 만나지 않은 경우 꼬리를 제거하고 머리를 추가한다.
map[nx][ny] = 2;
snake.addFirst(new point(nx, ny));
point tail = snake.removeLast();
map[tail.x][tail.y] = 0;
}
위의 두가지 경우는 사과인지 아닌지를 판단한다.
앞서 사과는 map 에 1로 저장을 해두었다.
<전체코드>
import java.io.*;
import java.util.*;
public class Main {
static StringBuilder sb = new StringBuilder();
static class point{
int x, y;
public point(int x, int y) {
this.x = x;
this.y = y;
}
}
static int[][] map;
static int[] time;
static int[] dir;
static int[] dx = {-1, 0, 1, 0};
static int[] dy = {0, 1, 0, -1};
public static void main(String[] args) throws IOException{
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(bufferedReader.readLine());
map = new int[n + 1][n + 1];
int number_Apple = Integer.parseInt(bufferedReader.readLine());
for(int i = 0 ; i < number_Apple ; i++) {
StringTokenizer st = new StringTokenizer(bufferedReader.readLine());
int y = Integer.parseInt(st.nextToken());
int x = Integer.parseInt(st.nextToken());
map[y][x] = 1;
}
int L = Integer.parseInt(bufferedReader.readLine());
dir = new int[L];
time = new int[L];
for(int i = 0 ; i < L ; i++) {
StringTokenizer st = new StringTokenizer(bufferedReader.readLine());
time[i] = Integer.parseInt(st.nextToken());
dir[i] = st.nextToken().equals("D") ? 1 : 3;
}
int timeIdx = 0;
int second = 0;
int snakeDir = 1;
map[1][1] = 2;
Deque<point> snake = new ArrayDeque<point>();
snake.add(new point(1, 1));
while(true) {
if(timeIdx < L && time[timeIdx] == second) {
snakeDir = (snakeDir + dir[timeIdx]) % 4;
timeIdx++;
}
int nx = snake.getFirst().x + dx[snakeDir];
int ny = snake.getFirst().y + dy[snakeDir];
if(nx <= 0 || nx > n || ny <= 0 || ny > n) {
System.out.println(second + 1);
break;
}
if(map[nx][ny] == 2) {
System.out.println(second + 1);
break;
}
if(map[nx][ny] == 1) {
map[nx][ny] = 2;
snake.addFirst(new point(nx, ny));
}
else if(map[nx][ny] == 0) {
map[nx][ny] = 2;
snake.addFirst(new point(nx, ny));
point tail = snake.removeLast();
map[tail.x][tail.y] = 0;
}
second++;
}
}
}
'자료구조 공부 > Queue, Stack' 카테고리의 다른 글
[백준] 1655 가운데를 말해요 (0) | 2021.10.29 |
---|---|
[백준] 17298 오큰수 (0) | 2021.08.22 |
[백준] 2504 괄호의 값 (0) | 2021.08.03 |
[프로그래머스] 야근 지수 (0) | 2021.06.22 |
[프로그래머스] 이중우선순위큐 (0) | 2021.05.23 |