Created
January 5, 2017 08:33
-
-
Save ben-x9/abf829bd85ea6dba87013073f6c5646a to your computer and use it in GitHub Desktop.
This file contains hidden or 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
// Tic Tac Toe State Machine | |
// interface that implements the following function | |
// makeMove(r, c) -> one of the following enum values describing the state of the game after the given move. | |
// 1. INCOMPLETE - the given moven was valid, there remain open spaces, and there are no winners. | |
// 2. INVALID -- the previous play was out of bounds (0 < x < 2), or a piece already occupied the given position | |
// 3. X_WINS -- X is winning along either a row, column, or diagonal | |
// 4. O_WINS -- same as above except for O | |
// 5. STALEMATE -- the previous move was valid, there are no winners, but there remain open spaces. | |
// makeMove is called alternatingly by X and O players (X is first). | |
// You will need to keep state as consecutive plays are made; I don't care where or how, as long as you can reset it. | |
// globals, function, closure, class | |
// You can assume that after any of 2-5 is returned, no other plays will be made for that board. | |
let board, numMarks; | |
function resetBoard() { | |
board = [ | |
[null, null, null], | |
[null, null, null], | |
[null, null, null] | |
]; | |
numMarks = 0; | |
} | |
resetBoard(); | |
function makeMove(row, col) { | |
if (invalidMove(row, col)) return 'INVALID'; | |
const player = currentPlayer(); | |
markBoard(player, row, col); | |
return moveResult(player, row, col); | |
} | |
const invalidMove = (row, col) => | |
outOfRange(row, col) || | |
isMarked(board[row][col]); | |
const currentPlayer = () => | |
isEven(numMarks) ? | |
'X' : | |
'O'; | |
function markBoard(player, row, col) { | |
board[row][col] = player; | |
numMarks++; | |
} | |
const moveResult = (player, row, col) => | |
testWin(player, row, col) ? | |
player + '_WINS' : | |
numMarks === 9 ? | |
'STALEMATE' : | |
'INCOMPLETE'; | |
const outOfRange = (row, col) => | |
row < 0 || row > 2 || | |
col < 0 || col > 2; | |
const isMarked = (x) => | |
x !== null; | |
const isEven = (n) => | |
n % 2 === 0 | |
const testWin = (player, row, col) => | |
testWinRow(player, row) || | |
testWinCol(player, col) || | |
testWinDiags(player); | |
const testWinRow = (player, row) => | |
board[row][0] === player && | |
board[row][1] === player && | |
board[row][2] === player; | |
const testWinCol = (player, col) => | |
board[0][col] === player && | |
board[1][col] === player && | |
board[2][col] === player; | |
const testWinDiags = (player) => | |
testWinDiag1(player) || | |
testWinDiag2(player); | |
const testWinDiag1 = (player) => | |
board[0][0] === player && | |
board[1][1] === player && | |
board[2][2] === player; | |
const testWinDiag2 = (player) => | |
board[0][2] === player && | |
board[1][1] === player && | |
board[2][0] === player; | |
function assertPlay(row, col, expected) { | |
expected = expected || 'INCOMPLETE'; | |
const got = makeMove(row, col); | |
if (got !== expected) throw new Error("Got " + got + " Expected " + expected); | |
} | |
resetBoard(); | |
assertPlay(0, 1); | |
assertPlay(-2, 1, 'INVALID'); | |
resetBoard(); | |
assertPlay(0, 2); | |
assertPlay(-2, 1, 'INVALID'); | |
resetBoard(); | |
assertPlay(1, 3, 'INVALID'); | |
resetBoard(); | |
assertPlay(1, -1, 'INVALID'); | |
resetBoard(); | |
assertPlay(2, 0); | |
assertPlay(1, 1); | |
assertPlay(2, 1); | |
assertPlay(1, 2); | |
assertPlay(2, 2, 'X_WINS'); | |
resetBoard(); | |
assertPlay(0, 0); // X | |
assertPlay(1, 1); // O | |
assertPlay(0, 2); // X | |
assertPlay(2, 1); // O | |
assertPlay(1, 2); // X | |
assertPlay(0, 1, 'O_WINS') // O | |
resetBoard(); | |
assertPlay(1, 1); | |
assertPlay(1, 2); | |
assertPlay(0, 2); | |
assertPlay(2, 1); | |
assertPlay(2, 0, 'X_WINS'); | |
resetBoard(); | |
assertPlay(2, 1); | |
assertPlay(1, 1); // O | |
assertPlay(1, 2); // X | |
assertPlay(2, 2); // O | |
assertPlay(0, 1); // X | |
assertPlay(0, 0, 'O_WINS'); // O | |
resetBoard(); | |
assertPlay(0, 0); // X | |
assertPlay(0, 1); // O | |
assertPlay(0, 2); // X | |
assertPlay(1, 2); // O | |
assertPlay(1, 0); // X | |
assertPlay(2, 0); // O | |
assertPlay(1, 1); // X | |
assertPlay(2, 2); // O | |
assertPlay(2, 1, 'STALEMATE'); // X | |
console.log('Success'); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment