[구름톤 챌린지] GameJam
1ilsang
클라이밍 하실래염?
Published

끔찍한 시뮬레이션 문제이다.
별다른 특이 사항 없이 문제에서 제시한 대로 구현하면 된다.
접근법
구름과 플레이어 두 명이 각각 게임을 진행한다. 따라서 우리는 동일한 게임을 2번 실행해야 한다는 것을 알 수 있다.
즉 초기화를 잘하던가, 똑같은 코드를 두 번 실행해야 한다.
게임 보드 칸에는 이동 횟수와 방향이 적혀있으며 게이머가 놓은 위치에서부터 칸의 명령을 따라 쭉 실행하면 된다.
만약 보드를 이탈하는 경우(처음/끝) 반대쪽 첫 칸으로 이동하게 된다(-1 -> length -1
, length -> 0
),
이때 이전에 방문했던 곳에 다시 온다면 게임이 종료된다. 우리는 두 번의 메모 맵이 필요하다.
두 플레이어가 게임을 종료했을 때 점수를 비교해 출력한다.
정리
- 유저의 위치를 받아 점수를 반환하는 함수를 만든다(내부 변수 사용으로 초기화 용이).
- 이동 거리만큼 이동한다.
- 보드 이탈시 좌표를 반대쪽 첫 칸으로 재설정해 준다.
- 이동할 때마다 메모를 한다.
- 점수 값을 비교 출력한다.
최종 코드
const readline = require('readline');
let rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
let n;
const goorm = [];
const player = [];
const map = [];
const d = {
U: [-1, 0],
R: [0, 1],
D: [1, 0],
L: [0, -1],
};
const getBoardInfo = ({ r, c }) => {
const cmd = map[r][c];
const count = parseInt(cmd);
const direction = cmd.slice(-1);
return {
cmd,
count,
direction,
};
};
const setNextMove = ({ r, c, direction }) => {
let nr = r + d[direction][0];
let nc = c + d[direction][1];
if (nr < 0) {
nr = map.length - 1;
} else if (nc < 0) {
nc = map[0].length - 1;
} else if (nr >= map.length) {
nr = 0;
} else if (nc >= map[0].length) {
nc = 0;
}
return {
nr,
nc,
};
};
const buildMemo = () => {
const memo = map.map((row) => {
return Array(row.length).fill(0);
});
return memo;
};
const playGame = ({ r, c }) => {
// 최초 세팅. 현재 칸의 명령을 파싱한다.
let { cmd, count, direction } = getBoardInfo({ r, c });
let nr = r;
let nc = c;
let score = 1;
const memo = buildMemo();
memo[r][c] = 1;
while (true) {
// 이동 횟수가 0이라면 현재 위치 칸의 명령으로 초기화 한다.
if (count === 0) {
const curValues = getBoardInfo({ r: nr, c: nc });
cmd = curValues.cmd;
count = curValues.count;
direction = curValues.direction;
}
// 다음 이동을 위해 nextRow, nextCol 값을 세팅한다.
const nextPosition = setNextMove({ r: nr, c: nc, direction });
nr = nextPosition.nr;
nc = nextPosition.nc;
// 만약 다음 좌표가 방문한적이 있다면 루프를 종료한다.
if (memo[nr][nc]) {
break;
}
// 이동 거리를 감소시키고 스코어를 추가한뒤 좌표를 메모한다.
count--;
score++;
memo[nr][nc] = 1;
}
return score;
};
const getParsedLineNumbers = (line) =>
line.split(' ').map((num) => Number(num) - 1);
const setFields = (line) => {
const parsedLine = line.split(' ');
map.push(parsedLine);
};
rl.on('line', (line) => {
if (n === undefined) {
n = Number(line);
return;
}
if (goorm.length === 0) {
goorm.push(...getParsedLineNumbers(line));
return;
}
if (player.length === 0) {
player.push(...getParsedLineNumbers(line));
return;
}
if (map.length < n) {
setFields(line);
if (map.length < n) {
return;
}
}
const gScore = playGame({
r: goorm[0],
c: goorm[1],
});
const pScore = playGame({
r: player[0],
c: player[1],
});
const answer = gScore > pScore ? `goorm ${gScore}` : `player ${pScore}`;
console.log(answer);
rl.close();
});