
내가 생각했을때 문제에서 원하는부분
첫째 줄에 보드의 크기 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가 증가하는 순으로 주어진다.
첫째 줄에 게임이 몇 초에 끝나는지 출력한다.
내가 이 문제를 보고 생각해본 부분
입력 처리 및 보드 초기화
먼저 보드 크기 N과 사과 개수 K를 입력받는다.
2차원 배열 board를 만들어서, 사과가 있는 위치는 1로 표시한다.
뱀은 처음에 (0,0) 위치에 있으며 몸통을 나타내는 2로 표시한다.
방향 변환 명령 입력 처리
뱀의 방향 전환 횟수 L을 받아서, 각 변환 시점(초)과 방향('L' 또는 'D')을 배열에 저장한다.
뱀 상태 관리 - 덱 사용
snake라는 덱(Deque)을 사용하여 뱀의 몸통 좌표를 관리한다.
덱의 앞부분은 뱀 머리 위치이며, 뒷부분은 꼬리 위치가 된다.
새 위치로 머리가 이동하면 덱 앞에 좌표를 추가하고, 사과가 없으면 꼬리 좌표를 덱 뒤에서 제거한다.
이동과 충돌 검사
moves 배열로 현재 뱀 방향에 따라 머리를 이동시킬 좌표 변화를 지정한다.
매 초마다:
머리 위치에서 방향에 맞춰 다음 칸 좌표(nr, nc)를 계산한다.
만약 다음 칸이 벽 범위를 벗어나거나 뱀 몸통(2)이 있다면 게임 종료한다.
사과 처리와 꼬리 이동
다음 칸에 사과가 있으면, 사과를 없애고 그 칸을 몸통(2)으로 바꾸며 꼬리는 움직이지 않아 뱀 길이가 늘어난다.
사과가 없으면 머리를 몸통 위치로 이동시키고, 꼬리를 한 칸 줄여 해당 칸을 빈칸(0)으로 만든다.
방향 변화 업데이트
입력받은 시간 배열과 일치하면 현재 방향을 왼쪽 또는 오른쪽으로 90도 돌린다.
왼쪽 회전은 dir = (dir + 3) % 4
오른쪽 회전은 dir = (dir + 1) % 4
방향을 0~3 사이 숫자로 관리하며, 순환하도록 모듈러 연산을 사용한다.
종료 조건 및 시간 출력
벽이나 몸통 충돌 시 무한 루프를 빠져나오고, 그 시점의 시간을 출력하여 게임 종료 시간(초)을 구한다.
코드로 구현
package baekjoon.baekjoon_33;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Deque;
import java.util.LinkedList;
import java.util.StringTokenizer;
// 백준 3190번 문제
public class Main1317 {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int N = Integer.parseInt(br.readLine());
int K = Integer.parseInt(br.readLine());
// 보드 초기화: 0 빈칸, 1 사과, 2 뱀 몸통
int[][] board = new int[N][N];
for (int i = 0; i < K; i++) {
StringTokenizer st = new StringTokenizer(br.readLine());
int r = Integer.parseInt(st.nextToken()) - 1;
int c = Integer.parseInt(st.nextToken()) - 1;
board[r][c] = 1; // 사과 위치 표시
}
int L = Integer.parseInt(br.readLine());
int[] times = new int[L];
char[] directions = new char[L];
for (int i = 0; i < L; i++) {
StringTokenizer st = new StringTokenizer(br.readLine());
times[i] = Integer.parseInt(st.nextToken());
directions[i] = st.nextToken().charAt(0);
}
// 덱으로 뱀 위치 관리 (머리 앞쪽)
Deque<int[]> snake = new LinkedList<>();
snake.add(new int[] {0, 0});
board[0][0] = 2; // 뱀 위치 표시
// 방향 변환: 동(0,1), 남(1,0), 서(0,-1), 북(-1,0)
int[][] moves = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
int dir = 0; // 초기 방향 오른쪽
int time = 0; // 경과 시간
int idx = 0; // 방향 변환 인덱스
while (true) {
time++;
// 현재 머리 위치
int[] head = snake.peekFirst();
int nr = head[0] + moves[dir][0];
int nc = head[1] + moves[dir][1];
// 벽 충돌 검사
if (nr < 0 || nr >= N || nc < 0 || nc >= N)
break;
// 자신의 몸과 충돌 검사
if (board[nr][nc] == 2)
break;
// 사과가 있으면
if (board[nr][nc] == 1) {
board[nr][nc] = 2;
snake.addFirst(new int[] {nr, nc});
} else { // 사과 없으면 꼬리 제거
board[nr][nc] = 2;
snake.addFirst(new int[] {nr, nc});
int[] tail = snake.removeLast();
board[tail[0]][tail[1]] = 0;
}
// 방향 전환 처리
if (idx < L && time == times[idx]) {
if (directions[idx] == 'L') {
dir = (dir + 3) % 4; // 왼쪽 회전
} else {
dir = (dir + 1) % 4; // 오른쪽 회전
}
idx++;
}
}
System.out.println(time);
br.close();
}
}
코드와 설명이 부족할수 있습니다. 코드를 보시고 문제가 있거나 코드 개선이 필요한 부분이 있다면 댓글로 말해주시면 감사한 마음으로 참고해 코드를 수정 하겠습니다.