N x N 크기의 보드판에는 K개의 사과들이 존재한다. 1의 길이를 시작으로 좌측상단에서 오른쪽 방향으로 출발한 뱀은 매초 1칸씩 움직인다. 만약 움직인 칸에 사과가 있다면 사과를 먹고 길이가 1 늘어난다. 즉, 꼬리는 움직이지 않는다. 특정 시간에는 머리의 방향을 돌리는데 L은 왼쪽 D는 오른쪽이며 해당 시간에 움직임을 끝낸 후 방향을 돌린다. 뱀이 벽이나 자신에게 부딪혔을 때의 게임 시간을 구한다.
int N = Integer.parseInt(reader.readLine()); // Input : Size of board
int K = Integer.parseInt(reader.readLine()); // Input : Number of apple
Dummy dummy = new Dummy(N); // Dummy Game
// Input : Add apples to the game board
StringTokenizer tokenizer;
while (K-- > 0) {
tokenizer = new StringTokenizer(reader.readLine());
dummy.addApple(
Integer.parseInt(tokenizer.nextToken()) - 1,
Integer.parseInt(tokenizer.nextToken()) - 1
);
}
// Input : Add turning actions to the game
int turnNum = Integer.parseInt(reader.readLine());
while (turnNum-- > 0) {
tokenizer = new StringTokenizer(reader.readLine());
dummy.addTurn(
Integer.parseInt(tokenizer.nextToken()),
tokenizer.nextToken().charAt(0)
);
}
// Output : Time when game ended
result.append(dummy.playGame());
class Dummy {
private final int[][] moves = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}}; // Moves
private int headRow, headCol, tailRow, tailCol; // Location of head and tail
private final int[][] board; // -1 : Apple / 1, 2, 3, 4 : Snake with direction
private final Queue<Turn> turns = new LinkedList<>(); // Turning actions with time
public Dummy(int boardSize) {
board = new int[boardSize][boardSize];
board[0][0] = 2;
}
/**
* Add apple
* @param row Row location of apple
* @param col Column location of apple
*/
public void addApple(int row, int col) {
board[row][col] = -1;
}
/**
* Add turning action
* @param time Turning time
* @param dir Turning direction
*/
public void addTurn(int time, char dir) {
turns.offer(new Turn(time, dir));
}
/**
* Play game until game ends
* @return Time when game ends
*/
public int playGame() {
int time = 0;
while (true) {
try {
time++;
move();
turn(time);
} catch (ArrayIndexOutOfBoundsException e) { // Game ends
return time;
}
}
}
/**
* Move snake
*/
private void move() {
// Move head
int nextRow = headRow + moves[board[headRow][headCol] - 1][0];
int nextCol = headCol + moves[board[headRow][headCol] - 1][1];
// Crashes to itself
if (board[nextRow][nextCol] > 0) throw new ArrayIndexOutOfBoundsException();
boolean grow = board[nextRow][nextCol] == -1;
board[nextRow][nextCol] = board[headRow][headCol];
headRow = nextRow;
headCol = nextCol;
// Move tail if didn't grow
if (!grow) {
nextRow = tailRow + moves[board[tailRow][tailCol] - 1][0];
nextCol = tailCol + moves[board[tailRow][tailCol] - 1][1];
board[tailRow][tailCol] = 0;
tailRow = nextRow;
tailCol = nextCol;
}
}
/**
* Turn head's direction
* @param time Time of game
*/
private void turn(int time) {
if (!turns.isEmpty() && turns.peek().time == time) {
Turn turn = turns.poll();
board[headRow][headCol] = ((board[headRow][headCol] - 1)
+ (turn.dir == 'L' ? 3 : 1)) % 4 + 1;
}
}
}
class Turn {
int time;
char dir;
public Turn(int time, char dir) {
this.time = time;
this.dir = dir;
}
}