Skip to content

Instantly share code, notes, and snippets.

@heatherbooker
Last active September 7, 2016 02:11
Show Gist options
  • Save heatherbooker/5f80f1e46ba79bc628c3b56b72bdf45e to your computer and use it in GitHub Desktop.
Save heatherbooker/5f80f1e46ba79bc628c3b56b72bdf45e to your computer and use it in GitHub Desktop.
Improved version of ticTacToe for command line
function chooseMove(board) {
function getAvailableLocations() {
var availableLocations = [];
for (var location in board) {
// Since key === value is the default, if this is true,
// it means the spot has not yet been played.
if (location === board[location]) {
availableLocations.push(location);
}
}
return availableLocations;
}
var locationToChose;
var counter = 0;
getAvailableLocations().forEach(function(location) {
// For the n-th location in the array, there is a 1/n chance of it being selected.
if (Math.random() < 1 / counter++) {
locationToChose = location;
}
});
return locationToChose;
}
function takeTurn(board, symbol) {
return new Promise((resolve, reject) => {
// Pausing for a moment makes the game feel more natural.
setTimeout(function() {
var location = chooseMove(board);
board[location] = symbol;
resolve();
}, 800);
});
}
exports.takeTurn = takeTurn;
module.exports = {
togglePlayer(player) {
if (player === '1') {
return '2';
}
return '1';
},
checkStatus(board, counter) {
function isTied() {
return counter < 9 ? false : true;
}
var winner;
function checkForWinningStreak(board, triad) {
if (board[triad[0]] === board[triad[1]]) {
if (board[triad[1]] === board[triad[2]]) {
winner = board[triad[0]];
return true;
}
}
return false;
}
function matchesWinningPattern() {
var triads = [['A1','A2','A3'], ['B1','B2','B3'], ['C1','C2','C3'],
['A1','B1','C1'], ['A2','B2','C2'], ['A3','B3','C3'],
['A1','B2','C3'], ['A3','B2','C1']];
var matches = triads.filter(function(triad) {
return checkForWinningStreak(board, triad);
});
return matches.length > 0;
}
if (matchesWinningPattern()) {
return 'Winner:' + winner + 's!';
} else if (isTied()) {
return 'Tied';
} else {
return false;
}
}
}
module.exports = {
printBoard(board) {
console.log(`
${board.A1} | ${board.B1} | ${board.C1}\n
___|____|___\n
| | \n
${board.A2} | ${board.B2} | ${board.C2}\n
___|____|___\n
| | \n
${board.A3} | ${board.B3} | ${board.C3}
`);
},
prompt(player, symbol, isVsComputer, rl) {
function getPrompt() {
if (isVsComputer) {
if (player === '2') {
return 'Computer\'s turn!';
}
}
return `Player ${player} (${symbol} ), please enter the location you would like to play next: `;
}
rl.setPrompt(getPrompt());
rl.prompt();
}
}
var readline = require('readline');
// Computer contains functions for one-player (vs. computer) games.
var computer = require('./computer.js');
// Interface displays text to user.
var interface = require('./interface.js');
// Games contains helper functions specific to the proceedings of the game.
var game = require('./game.js');
var rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
function playTheGame(isVsComputer) {
var board = {
A1: 'A1', A2: 'A2', A3: 'A3',
B1: 'B1', B2: 'B2', B3: 'B3',
C1: 'C1', C2: 'C2', C3: 'C3'
};
var playerMap = {'1': ' X', '2': ' O'};
var currentPlayer = '1';
var counter = 0;
interface.printBoard(board);
interface.prompt(currentPlayer, playerMap[currentPlayer], isVsComputer, rl);
// rl.on('line') callback will run every time user presses 'enter' key on keyboard.
rl.on('line', function(input) {
var location = input.toUpperCase();
// The value should equal the key; otherwise, the location has already been played.
if (location === board[location]) {
board[location] = playerMap[currentPlayer];
// afterEveryMove returns true to continue game, false if game is over.
if (afterEveryMove() && isVsComputer) {
// computer.takeTurn uses setTimeout with a promise.
computer.takeTurn(board, playerMap[currentPlayer])
.then(() => {
afterEveryMove();
});
}
} else {
interface.printBoard(board);
console.log('You can\'t do that! Try again:');
}
});
function afterEveryMove() {
counter ++;
interface.printBoard(board);
var gameStatus = game.checkStatus(board, counter);
if (gameStatus) {
console.log('Game over!', gameStatus);
rl.close();
return false;
} else {
currentPlayer = game.togglePlayer(currentPlayer);
interface.prompt(currentPlayer, playerMap[currentPlayer], isVsComputer, rl);
return true;
}
}
}
rl.question('To play against a friend, press 1; To play against the computer, press 2: ', function (response) {
if (response === '1') {
playTheGame(false);
} else {
playTheGame(true);
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment