Skip to content

Instantly share code, notes, and snippets.

@renatocassino
Last active August 16, 2018 03:17
Show Gist options
  • Save renatocassino/826047a49abd78c3ddd41269535eb86f to your computer and use it in GitHub Desktop.
Save renatocassino/826047a49abd78c3ddd41269535eb86f to your computer and use it in GitHub Desktop.
2048 game
const readlineSync = require('readline-sync');
const printBoard = (board) => {
const f = (n) => {
const size = n.toString().length;
const spaces = 5-size;
return ' '.repeat(spaces) + n.toString() + ' ';
};
textToPrint = [];
textToPrint.push('-'.repeat(4*5+5));
board.forEach((column, idxLine) => {
const line = column.map((_, idxColumn) => f(board[idxColumn][idxLine]));
textToPrint.push(line.join('|'));
});
textToPrint.push('-'.repeat(4*5+5));
console.log(textToPrint.join("\n"));
return board;
};
const getEmptyBlocks = (board) => (
board.reduce((lineData, line, idxColumn) => {
const result = line.reduce((data, row, idx) => {
if (row !== 0) return data;
return [[idxColumn, idx], ...data];
}, []);
return [...lineData, ...result];
}, [])
);
const getRandomIndex = (zeros) => zeros[parseInt(Math.random() * zeros.length)];
const addNumber = (board, [columnIndex, lineIndex], number=2) => {
const line = board[columnIndex];
const newLine = [
...line.slice(0, lineIndex),
number,
...line.slice(lineIndex + 1, line.length),
];
return [
...board.slice(0, columnIndex),
newLine,
...board.slice(columnIndex + 1, board.length),
];
};
const compose = (...fns) => fns.reduce((f, g) => (...args) => f(g(...args)));
const generateArraySize = (size, defaultValue = 0) => Array.from({ length: size }, () => defaultValue);
const arrayPad = (size = 4) => arr => (
[...arr, ...generateArraySize(size - arr.length)]
);
const moveLineUp = (line) => {
const moveLineUpInner = (currentLine, results=[]) => {
if (currentLine.length === 0) return results;
if(currentLine[0] === currentLine[1]) {
const total = currentLine[0] + currentLine[1];
return moveLineUpInner(currentLine.slice(2), [...results, total]);
}
return moveLineUpInner(currentLine.slice(1), [...results, currentLine[0]]);
};
return arrayPad(line.length)(moveLineUpInner(line.filter((n)=>n > 0)), line.length); // Array pad here
};
const moveBoardUp = (board) => board.map(line => moveLineUp(line));
const flipRight = matrix => (
matrix[0].map((_, index) => (
matrix.map(row => row[index])
)).reverse());
const moveBoardRight = board => (
compose(
flipRight,
moveBoardUp,
flipRight,
flipRight,
flipRight
)(board)
);
const moveBoardDown = (board) => (
compose(
flipRight,
flipRight,
moveBoardUp,
flipRight,
flipRight
)(board)
);
const moveBoardLeft = board => (
compose(
flipRight,
flipRight,
flipRight,
moveBoardUp,
flipRight
)(board)
);
const hasNumberInBoard = (board, number) => (
board.some((line) => line.some((block) => block === number))
);
const isLooser = board => (
!hasNumberInBoard(board, 0)
);
const isWinner = board => (
hasNumberInBoard(board, 2048)
);
const getRandomPosition = compose(getRandomIndex, getEmptyBlocks);
const addRandomNumber = (board) => {
const position = getRandomPosition(board);
return addNumber(board, position);
};
const askMovement = () => {
while(true) {
const movement = readlineSync.question("Make your movement using the keys [w,a,s,d]:");
if(movement.match(/^[wasd]$/)) {
return movement;
}
}
};
const arraysEqual = (arr1, arr2) => JSON.stringify(arr1) === JSON.stringify(arr2);
const moveTo = (board, movement) => {
switch(movement) {
case 'w': return moveBoardUp(board);
case 'a': return moveBoardLeft(board);
case 's': return moveBoardDown(board);
case 'd': return moveBoardRight(board);
}
};
const move = (board) => { // Move
const movement = askMovement();
const movedBoard = moveTo(board, movement);
return (arraysEqual(movedBoard, board))
? move(board)
: movedBoard;
};
const finishGame = (board) => {
if (isWinner(board)) {
console.log("You win the game! Congrats! ;D");
process.exit(0);
}
if (isLooser(board)) {
console.log("You lost the game!");
process.exit(0);
}
return board;
};
const game = (board) => compose(
game,
addRandomNumber,
move,
printBoard,
finishGame
)(board);
const board = [[0,0,0,0], [0,0,0,0], [0,0,0,0], [0,0,0,0]];
compose(
game,
addRandomNumber,
addRandomNumber
)(board);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment