export const putBlockOnBoard = (
board: (string | number)[][],
newBlock: number[][],
position: number[],
rotation: number,
player: string,
flip = false,
): (string | number
)[][] => {
if (position.length !== 2) {
throw new Error('position length must be 2');
}
if (/0-3/.test(rotation.toString())) {
throw new Error('rotation must be included in 0-3');
}
let rotatedBlock = rotation === 0 ? newBlock : rotateBlock(newBlock, rotation);
if (flip) {
rotatedBlock = flipBlock(rotatedBlock);
}
const currentBoard = board;
if (isAvailableArea(currentBoard, rotatedBlock, position, player)) {
const x = rotatedBlock[0].length;
const y = rotatedBlock.length;
for (let i = 0; i < y; i += 1) {
for (let j = 0; j < x; j += 1) {
if (currentBoard[position[0] + i][position[1] + j] === 0 && rotatedBlock[i][j] === 1) {
currentBoard[position[0] + i][position[1] + j] = player;
}
}
}
}
return currentBoard;
};
우선 첫 취업 전후 및 0년차 햇병아리 시절 퇴사 이후 지원했던 회사의 신입 뽑던 실무자 분들께 사과의 말씀을 전해드리고 싶다. 당시 전념하던 팀 사이드 프로젝트 진행 중 어렸을 적 좋아하던 Blokus란 보드게임을 짬날 때마다 조금씩 구현하고 있었는데, 지금 돌아보니 참 그 누구도 읽고 싶지 않은 코드가 아닐 수가 없다. 이것이 내 서류 100탈의 비결이다.
export const isAvailableArea = (
board: (string | number)[][], block: number[][], position: number[], player: string,
): boolean => {
if (position[1] + block[0].length > 20 || position[0] + block.length > 20) {
throw new Error('range out');
}
const x = block[0].length;
const y = block.length;
const affectedArea: (number | string)[][] = [];
const regExpY = new RegExp(`0|${20 - y}`);
const regExpX = new RegExp(`0|${20 - x}`);
if (regExpY.test(position[0].toString()) && regExpX.test(position[1].toString())) {
if (((position[0] === 0
&& ((player === 'a' && position[1] === 0 && block[0][0] === 1)
|| (player === 'd' && position[1] === 20 - x && block[0][block[0].length - 1] === 1)))
|| (position[0] === 20 - y
&& ((player === 'b' && position[1] === 0 && block[block.length - 1][0] === 1)
|| (player === 'c' && position[1] === 20 - x && block[block.length - 1][block[0].length - 1] === 1))))) {
return true;
}
if (((position[0] === 0
&& ((player === 'a' && position[1] === 0 && block[0][0] !== 1)
|| (player === 'd' && position[1] === 20 - x && block[0][block[0].length - 1] !== 1)))
|| (position[0] === 20 - y
&& ((player === 'b' && position[1] === 0 && block[block.length - 1][0] !== 1)
|| (player === 'c' && position[1] === 20 - x && block[block.length - 1][block[0].length - 1] !== 1))))) {
throw new Error('no block on vertex');
}
}
for (let i = position[0] - 1; i <= position[0] + y; i += 1) {
for (let j = position[1] - 1; j <= position[1] + x; j += 1) {
if ((i - position[0] === -1 && position[0] === 0)
|| i === 20) {
continue;
}
if (!affectedArea[i - position[0] + 1]) {
affectedArea[i - position[0] + 1] = [];
}
affectedArea[i - position[0] + 1][j - position[1] + 1] = board[i][j];
if (i - position[0] >= 0 && j - position[1] >= 0
&& i - position[0] < block.length && j - position[1] < block[0].length
&& block[i - position[0]][j - position[1]] === 1
&& affectedArea[i - position[0] + 1][j - position[1] + 1] !== 0) {
throw new Error('blocks folded');
}
if (i - position[0] >= 0 && j - position[1] >= 0
&& i - position[0] < block.length && j - position[1] < block[0].length
&& block[i - position[0]][j - position[1]] === 1
&& affectedArea[i - position[0] + 1][j - position[1] + 1] === 0) {
affectedArea[i - position[0] + 1][j - position[1] + 1] = 'n';
}
}
}
if (!affectedArea[0]) {
affectedArea.shift();
}
let flag = false;
for (let i = 0; i < affectedArea.length; i += 1) {
for (let j = 0; j < affectedArea[0].length; j += 1) {
if (affectedArea[i][j] === 'n'
&& ((i > 0
&& (affectedArea[i - 1][j - 1] === player
|| affectedArea[i - 1][j + 1] === player))
|| (i < affectedArea.length - 1
&& (affectedArea[i + 1][j + 1] === player
|| affectedArea[i + 1][j - 1] === player)))) {
flag = true;
}
if (affectedArea[i][j] === 'n' && (
(position[0] !== 0 && affectedArea[i - 1][j] === player)
|| affectedArea[i][j - 1] === player
|| (position[0] + y !== 20 && affectedArea[i + 1][j] === player)
|| affectedArea[i][j + 1] === player)) {
throw new Error('no adjacent block');
}
}
}
if (!flag) {
throw new Error('no block connected');
}
return true;
};
지금도 이 두 함수만 보더라도 도무지 손댈 엄두가 나지 않는다. 당시에는 저렇게 작성한 게임 로직을 가지고 SvelteKit을 통해 웹 서비스를 구현해보려고 했다. 1년 이상의 프리랜스 경험이 쌓인 지금의 나는 어떻게 달라졌는지 확인해보고자 벨로그에 글을 남기고자 한다.