Last active
October 18, 2015 23:16
-
-
Save spitis/47a243774808a9c124f9 to your computer and use it in GitHub Desktop.
Simple node tictactoe
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
var assert = require('assert'); | |
var readline = require('readline'); | |
var rl = readline.createInterface({ | |
input: process.stdin, | |
output: process.stdout | |
}); | |
function game() { | |
var board = [ | |
0,0,0, | |
0,0,0, | |
0,0,0]; | |
var turn = 1; //1 is player 1, -1 is player 2 | |
var gameOn = 0; //0 is a no game (newgame needs to be called); 1 is game | |
var compTurn = 0; | |
//returns true if any column or row contains all "player" | |
function checkColRow (player, board) { | |
var i, j; | |
var colCt = 0, rowCt = 0; | |
for (j = 0; j < 3; j++) { | |
for (i = 0; i < 3; i++) { | |
//check column i (e.g., indexes 0, 3, 6) | |
colCt += board[j + 3*i]; | |
//check row j (e.g., index 0, 1, 2) | |
rowCt += board[3*j + i]; | |
} | |
if ((colCt === 3*player) || (rowCt === 3*player)) {return true;} | |
colCt = 0; rowCt = 0; | |
} | |
return false; | |
} | |
assert(checkColRow(-1, [1,0,0, 0,1,0, 0,0,1]) === false); | |
assert(checkColRow(1, [1,0,0, 1,1,0, 1,0,1]) === true); | |
assert(checkColRow(-1, [0,0,-1, 0,1,-1, 0,0,-1]) === true); | |
assert(checkColRow(-1, [1,0,-1, -1,-1,-1, -1,0,1]) === true); | |
assert(checkColRow(-1, [0,0,0, 0,0,0, 0,0,0]) === false); | |
assert(checkColRow(1, [0,0,0, 1,1,1, 0,0,0]) === true); | |
//returns true if a diagonal contains all "player" | |
function checkDiag (player, board) { | |
var diagCt = 0, i; | |
//check 2, 4, 6 diagonal | |
for (i = 2; i< 7; i+=2) { | |
diagCt += board[i]; | |
} | |
//check 0, 4, 8 diagonal | |
if (diagCt === 3*player) {return true;} | |
diagCt = 0; | |
for (i = 0; i<9; i+=4) { | |
diagCt += board[i]; | |
} | |
return (diagCt === 3*player) ? true:false; | |
} | |
assert(checkDiag(-1, [1,0,0, 0,1,0, 0,0,1]) === false); | |
assert(checkDiag(1, [1,0,0, 0,1,0, 0,0,1]) === true); | |
assert(checkDiag(-1, [0,0,0, 0,1,0, 0,0,1]) === false); | |
assert(checkDiag(-1, [1,0,-1, 0,-1,0, -1,0,1]) === true); | |
function checkVictor (player,board) { | |
return checkColRow (player,board) || checkDiag (player,board); | |
} | |
function checkDraw (board) { | |
var i; | |
for (i = 0; i < 9; i++) { | |
if (board[i] === 0) return false; | |
} | |
return true; | |
} | |
function tryMove (player, x, y) { | |
if (x>3) {throw "illegal move";} | |
var idx = (3*(y-1) + x - 1); | |
if (board[idx] === 0) { | |
board[idx] = player; | |
} else { | |
throw "illegal move"; | |
} | |
} | |
//an actual move on the board | |
function move(y, x) { | |
try { | |
if (gameOn === 1) { | |
tryMove(turn, x, y); | |
printBoard(board); | |
if (checkVictor(turn, board)) { | |
console.log('Player ' + (turn === 1 ? "X" : "O") + ' wins!'); | |
//player wins | |
gameOn = 0; | |
turn = 0; | |
} else if (checkDraw(board)) { | |
gameOn = 0; | |
turn = 0; | |
console.log("Draw game!"); | |
} else { | |
turn = turn * -1; | |
if (compTurn === turn) { | |
console.log("Computer moves:"); | |
moveComp(); | |
} else { | |
console.log('Player ' + (turn === 1 ? "X" : "O") + ' to move.'); | |
} | |
} | |
} else { | |
console.log("No game is running. Use function newGame() to start a new game."); | |
} | |
} catch (e) { | |
console.log("Illegal move. Try again."); | |
} | |
} | |
//a hypothetical move function, takes a move, a board, and returns a board | |
//assumes the move is legal | |
function hypoMove(player,y,x,board) { | |
var idx = (3*(x-1) + y - 1); | |
var newBoard = board.slice(0); | |
newBoard[idx] = player; | |
return newBoard; | |
} | |
//returns the winning move, if there is one | |
function winningMove(player,legalMoves,board) { | |
var i, move; | |
for (i = 0; i < legalMoves.length; i++) { | |
move = legalMoves[i]; | |
if (checkVictor(player,hypoMove(player,move[0],move[1],board))) { | |
return move; | |
} | |
} | |
return false; | |
} | |
function legalMoves (board) { | |
var i; | |
var arr = []; | |
for (i = 0; i < board.length; i++) { | |
if (board[i]===0) { | |
arr.push([Math.floor((i/3)) +1, i % 3 +1]); | |
} | |
} | |
return arr; | |
} | |
assert(legalMoves([1,1,0, 1,1,1, 1,0,1])[0][0] === 1); | |
assert(legalMoves([1,1,0, 1,1,1, 1,0,1])[0][1] === 3); | |
assert(legalMoves([1,1,0, 1,1,1, 1,0,1])[1][0] === 3); | |
assert(legalMoves([1,1,0, 1,1,1, 1,0,1])[1][1] === 2); | |
function moveComp() { | |
var moves = legalMoves(board); | |
var compMove = winningMove(turn,moves.slice(0),board) || moves[Math.floor(Math.random() * moves.length)]; | |
move(compMove[0], compMove[1]); | |
} | |
function clearBoard () { | |
board = [0,0,0,0,0,0,0,0,0]; | |
} | |
function newGame (arg) { | |
console.log(); | |
console.log("******************"); | |
console.log(); | |
console.log("Starting new game."); | |
turn = 1; | |
gameOn = 1; | |
compPlayer = 0; | |
clearBoard(); | |
if (arg === "comp") { | |
compTurn = Math.random() > 0.5 ? 1 : -1; | |
} | |
if (compTurn === turn) { | |
console.log("Computer moves first:"); | |
moveComp(); | |
} else { | |
printBoard(board); | |
console.log(); | |
console.log("Player X to move. Use function move(row,col) to move."); | |
console.log(); | |
} | |
} | |
function XO (x) { | |
return (x===1) ? "X": (x===-1) ? "O" : " "; | |
} | |
function printBoard (board) { | |
var i; | |
console.log(" |_1_|_2_|_3_|"); | |
for (i = 1; i < 8; i+=3 ) { | |
console.log((i+2)/3 +': | ' + XO(board[i-1]) + ' | ' + XO(board[i]) + ' | ' + XO(board[i+1]) + ' |'); | |
} | |
} | |
var gameExport = { | |
newGame: newGame, | |
move: move, | |
moveComp: moveComp | |
}; | |
return gameExport; | |
} | |
var game = game(); | |
var newGame = game.newGame; | |
var move = game.move; | |
var moveComp = game.moveComp; | |
function quit() { | |
rl.close(); | |
rl = null; | |
} | |
function repl () { | |
rl && rl.question("",function (input) { | |
try { | |
eval(input); | |
} catch (e) { | |
console.log(e); | |
} finally { | |
repl(); | |
} | |
}); | |
} | |
console.log("*************************************************************"); | |
console.log("*** TIC TAC TOE ***"); | |
console.log("*************************************************************"); | |
console.log("*** Instructions: ***"); | |
console.log("*** newGame(): starts a new game ***"); | |
console.log("*** newGame('comp'): new game against a compute ***"); | |
console.log("*** move(y,x): make move at row y and col x ***"); | |
console.log("*************************************************************"); | |
newGame(); | |
repl(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment