dao-game / commit
Improved animation, but winning check isn't done yet.
game.js | 175 ++++++++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 131 insertions(+), 44 deletions(-) diff --git a/game.js b/game.js index 0efce2a..0715a22 100644 --- a/game.js +++ b/game.js @@ -1,3 +1,33 @@ +class Coord { + /** + * Creates an instance of Coord. + * @param {number} row + * @param {number} col + * @memberof Coord + */ + constructor(row, col) { + this.row = row; + this.col = col; + } + + /** + * @param {Coord} coord + * @memberof Coord + */ + add(coord) { + this.row += coord.row; + this.col += coord.col; + } + + /** + * @param {Coord} otherCoord + * @memberof Coord + */ + equals(otherCoord) { + return (this.col === otherCoord.col && this.row === otherCoord.col); + } +} + // Constants const selectedPieceClassName = 'selected-piece'; const selectedPlayerTextClassName = 'selected-player-text'; @@ -13,6 +43,24 @@ const board = [ ]; const rows = 4; const cols = 4; +// clock face directions +const allDirections = [ + { row: 1, col: 0 }, // up + { row: 1, col: 1 }, // up-right + { row: 0, col: 1 }, // right + { row: -1, col: 1 }, // right-down + { row: -1, col: 0 }, // down + { row: -1, col: -1 }, // down-left + { row: 0, col: -1 }, // left + { row: 1, col: -1 }, // left-up +] +/** @type {Coord[]} */ +const squareCoords = [ + new Coord(0, 0), + new Coord(3, 0), + new Coord(3, 3), + new Coord(0, 3), +]; // DOM references const cells = () => Array.from(document.querySelectorAll("td")); @@ -46,18 +94,6 @@ const removeListeners = () => { listeners.length = 0; } -class Coord { - /** - * Creates an instance of Coord. - * @param {number} row - * @param {number} col - * @memberof Coord - */ - constructor(row, col) { - this.row = row; - this.col = col; - } -} /** * @param {Coord} data * @return {number} @@ -73,23 +109,13 @@ const coordToBoardIndex = ({ row, col }) => { const boardIndexToCoord = (index) => { const col = index % 4; const row = Math.floor(index / 4); - return { row, col }; + return new Coord(row, col); }; const resetBoard = () => { - // resetPieces - /** @param {Element} piece */ - const resetPiece = (piece) => { - //piece.classList.remove(selectedPieceClassName); - // piece.classList.remove(activePlayerPieceClassName); - }; - redPieces().forEach(resetPiece); - bluePieces().forEach(resetPiece); - // resetCells cells().forEach(cell => { cell.classList.remove(blinkingClassName); - cell.style.zIndex = 0 }); // remove all listeners @@ -116,20 +142,9 @@ const setActivePlayerPieces = () => { * @returns {number[]} */ const getAllowedMoveIndicesForIndex = (boardIndex) => { - // clock face directions - const directions = [ - { row: 1, col: 0 }, // up - { row: 1, col: 1 }, // up-right - { row: 0, col: 1 }, // right - { row: -1, col: 1 }, // right-down - { row: -1, col: 0 }, // down - { row: -1, col: -1 }, // down-left - { row: 0, col: -1 }, // left - { row: 1, col: -1 }, // left-up - ] const coord = boardIndexToCoord(boardIndex); - const farthestCoords = directions + const farthestCoords = allDirections .map(direction => getFarthestCoord(coord, direction)) .filter(farCoord => farCoord !== undefined); @@ -175,8 +190,6 @@ const getPieceElementById = (pieceId) => { /** @param {Event} event */ const selectPiece = (event) => { - // resetBoard(); - // setActivePlayerPieces(); const previousSelectedPieceId = selectedPieceId; if (previousSelectedPieceId >= 0) { const previousPiece = getPieceElementById(previousSelectedPieceId); @@ -225,12 +238,6 @@ const makeMove = (destIndex) => { const cellWidth = cells()[0].clientWidth; const cellHeight = cells()[0].clientHeight; - const diffX = coordDiff.col * cellWidth; - const diffY = coordDiff.row * cellHeight; - - // const startCell = cells()[pieceIndex]; - // const destCell = cells()[destIndex]; - removeListeners(); const animation = piece.animate([ @@ -252,9 +259,10 @@ const makeMove = (destIndex) => { board[pieceIndex] = null; board[destIndex] = pieceId; - checkForWin(); const elem = getPieceElementById(pieceId); elem.classList.remove(selectedPieceClassName); + + checkForWin(); nextMove(); }; } @@ -282,8 +290,87 @@ const nextMove = () => { setActivePlayerPieces(); }; +/** + * @param {Element[]} elements + * @returns {number[]} + */ +const elementsToBoardIndexes = (elements) => { + const indices = elements.map(pp => { + const pieceId = Number.parseInt(pp.id); + const pieceIndex = board.indexOf(pieceId); + return pieceIndex; + }); + return indices; +}; +/** + * @param {Element[]} elements + * @return {Coord[]} + */ +const elementsToCoords = (elements) => { + const indices = elementsToBoardIndexes(elements); + const coords = indices.map(pieceIndex => boardIndexToCoord(pieceIndex)); + return coords; +}; + +/** + * @param {Coord[]} coords + * @returns {boolean} + */ +const doCoordsFormSquare = (coords) => { + const areInSquare = coords.some((cornerCoord) => { + const offsetCoords = allDirections.map(d => cornerCoord.add(d)); + const presentOffsets = coords.filter(c => offsetCoords.includes(c)).length; + const isSquare = presentOffsets === 4; + return isSquare; + }); + return areInSquare; +}; + const checkForWin = () => { console.error(`testing win for ${isRedTurn ? 'red' : 'blue'}`); + return; + + const playerCoords = elementsToCoords( + isRedTurn ? redPieces() : bluePieces()) + const otherCoords = elementsToCoords( + isRedTurn ? bluePieces() : redPieces()); + + // winning conditions: + // 1. all in one row + // 2. all in one column + // 3. all in corners + // 4. all in square + // losing conditions: + // 1. on three sides of an opponent + + const firstPiece = playerCoords[0]; + const allInRow = playerCoords.every(pc => pc.row === firstPiece.row) + const allInCol = playerCoords.every(pc => pc.col === firstPiece.col) + const allInCorners = playerCoords.every(pc => squareCoords.filter(sc => pc.equals(sc)).length > 0); + const allInSquare = doCoordsFormSquare(playerCoords); + + const winnerName = isRedTurn ? 'Red' : 'Blue'; + let isWinner = false; + if (allInRow) { + alert(`${winnerName} wins by forming a row`) + isWinner = true; + } + if (allInCol) { + alert(`${winnerName} wins by forming a column`) + isWinner = true; + } + if (allInCorners) { + alert(`${winnerName} wins by putting pieces in corners`) + isWinner = true; + } + if (allInSquare) { + alert(`${winnerName} wins by forming a square`) + isWinner = true; + } + + if (isWinner) { + document.location.reload(); + } };