Algorithm/BOJ
[ BOJ ] 3190 뱀 G5 삼성 기출(JAVA)
_cpdm_
2021. 9. 2. 22:11
반응형
3190번: 뱀
'Dummy' 라는 도스게임이 있다. 이 게임에는 뱀이 나와서 기어다니는데, 사과를 먹으면 뱀 길이가 늘어난다. 뱀이 이리저리 기어다니다가 벽 또는 자기자신의 몸과 부딪히면 게임이 끝난다. 게임
www.acmicpc.net
문제 이해 |
- 'Dummy' 라는 도스게임이 있다. - 이 게임에는 뱀이 나와서 기어다니는데, 사과를 먹으면 뱀 길이가 늘어난다. - 뱀이 이리저리 기어다니다가 벽 또는 자기자신의 몸과 부딪히면 게임이 끝난다. - 게임은 NxN 정사각 보드위에서 진행되고, 몇몇 칸에는 사과가 놓여져 있다. - 보드의 상하좌우 끝에 벽이 있다. - 게임이 시작할때 뱀은 맨위 맨좌측에 위치하고 뱀의 길이는 1 이다. - 뱀은 처음에 오른쪽을 향한다. - 뱀은 매 초마다 이동을 하는데 다음과 같은 규칙을 따른다.
- 첫째 줄에 보드의 크기 N이 주어진다. (2 ≤ N ≤ 100) - 다음 줄에 사과의 개수 K가 주어진다. (0 ≤ K ≤ 100) - 다음 K개의 줄에는 사과의 위치가 주어지는데, 첫 번째 정수는 행, 두 번째 정수는 열 위치를 의미한다. - 사과의 위치는 모두 다르며, 맨 위 맨 좌측 (1행 1열) 에는 사과가 없다. - 다음 줄에는 뱀의 방향 변환 횟수 L 이 주어진다. (1 ≤ L ≤ 100) - 다음 L개의 줄에는 뱀의 방향 변환 정보가 주어지는데, 정수 X와 문자 C로 이루어져 있으며 게임 시작 시간으로부터 X초가 끝난 뒤에 왼쪽(C가 'L') 또는 오른쪽(C가 'D')로 90도 방향을 회전시킨다는 뜻이다. - X는 10,000 이하의 양의 정수이며, 방향 전환 정보는 X가 증가하는 순으로 주어진다. |
아이디어 |
- 시뮬은 하라는 대로 ! - 뱀을 어떤식으로 구현할 지 고민하다가 Deque을 이용했다. - 머리 방향은 우 0 하 1 좌 2 상 3 으로 지정해주었다. (시작이 오른쪽이라서..) - 머리 기준 오른쪽은 현방향에서 +1, 왼쪽은 현방향 -1 로 해주었다. |
코드 |
import java.io.*;
import java.util.*;
public class Main {
static class Order {
int sec;
String dir;
Order(int sec, String dir) {
this.sec = sec;
this.dir = dir;
}
}
static int N, map[][];
static final int blank = 0, apple = 2;
static Queue<Order> orders = new LinkedList<>();
static Deque<int[]> snakes = new LinkedList<>();
static int[][] dir = { { 0, 1, 0, -1 }, { 1, 0, -1, 0 } };
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = null;
N = stoi(br.readLine());
map = new int[N][N];
int appleCount = stoi(br.readLine());
for (int i = 0; i < appleCount; ++i) {// apple 위치를 입력받는다.
st = new StringTokenizer(br.readLine(), " ");
map[stoi(st.nextToken()) - 1][stoi(st.nextToken()) - 1] = apple;
}
int orderCount = stoi(br.readLine());
for (int i = 0; i < orderCount; ++i) {
st = new StringTokenizer(br.readLine(), " ");
orders.offer(new Order(stoi(st.nextToken()), st.nextToken()));
}
System.out.println(process());
}
static int process() {
snakes.offer(new int[] { 0, 0 });// 뱀의 첫 위치.
int time = 0;// 현재 시간
int snakeDir = 0;// R 0 D 1 L 2 R 3
boolean isGameOver = false;
while (true) { // 게임이 끝날때까지.
++time; // 시간 카운팅.
int[] newHead = {snakes.getLast()[0] + dir[0][snakeDir], snakes.getLast()[1] + dir[1][snakeDir]};
if (!isBoundary(newHead[0], newHead[1]) || isCrashBody(newHead)) {//새로이동할 위치가 벽이면 게임오버.
isGameOver = true;
break;
}
snakes.offer(newHead); // 괜찮으면 넣어준다.
// 이동할 위치가 사과가 있는지 없는지 여부.
if (isApple(snakes.getLast()[0], snakes.getLast()[1])) {
map[snakes.getLast()[0]][snakes.getLast()[1]] = blank; // 사과를 비운다.
} else { // 사과가 없으면 꼬리를 자른다.
snakes.pollFirst();
}
// 회전
if (!orders.isEmpty() && time == orders.peek().sec) { // 명령을 수행할 수 있는 초가 지났다면
String newDir = orders.poll().dir; // 새로운 방향을 입력받는다.
snakeDir = newDir.equals("D") ? snakeDir + 1 : snakeDir - 1;
snakeDir = snakeDir < 0 ? 3 : (snakeDir > 3 ? 0 : snakeDir); // 값 보정
}
if (isGameOver) break;
}
return time;
}
static boolean isCrashBody(int[] head) {
for(int[] now : snakes) { // 몸통이랑 박으면 true 반환
if(now[0] == head[0] && now[1]==head[1]) return true;
}
return false;
}
static boolean isBoundary(int x, int y) {
return 0 <= x && x < N && 0 <= y && y < N;
}
static boolean isApple(int x, int y) {
return map[x][y] == apple;
}
static int stoi(String s) {
return Integer.parseInt(s);
}
}
CPDM
choppadontbiteme.tistory.com
반응형