Last active
August 16, 2018 03:17
-
-
Save renatocassino/826047a49abd78c3ddd41269535eb86f to your computer and use it in GitHub Desktop.
2048 game
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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