Last active
March 23, 2016 22:27
-
-
Save bigomega/86c67796b032f8fc74e6 to your computer and use it in GitHub Desktop.
simple tic-tac-toe
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
| 'use strict' | |
| const fs = require('fs') | |
| // util function modified from github.com/bucaran/sget | |
| const readLineSync = function(message) { | |
| message = message || '' | |
| const win32 = () => 'win32' === process.platform | |
| const readSync = function(buffer) { | |
| var fd = win32() ? process.stdin.fd : fs.openSync('/dev/stdin', 'rs') | |
| var bytes = fs.readSync(fd, buffer, 0, buffer.length) | |
| if (!win32()) fs.closeSync(fd) | |
| return bytes | |
| } | |
| return (function(buffer) { | |
| try { | |
| process.stdout.write(message + ' ') | |
| return buffer.toString(null, 0, readSync(buffer)) | |
| } catch (e) { | |
| throw e | |
| } | |
| }(new Buffer(256))) | |
| } | |
| const coin = ['_', 'X', 'O'] | |
| const range = n => Array(n + 1).join(1).split('').map((x, i) => i) | |
| function end() { | |
| const verticalEnd = range(game.width).some(i => { | |
| const column = game.board[i] || [] | |
| const max = { p: 0, val: 0 } | |
| return range(game.height).some(j => { | |
| const value = column[j] | |
| if (value && value === max.p) max.val++ | |
| else max.p = value, max.val = 1 | |
| return max.p && max.val >= game.win | |
| }) | |
| }) | |
| const horizontalEnd = range(game.height).some(j => { | |
| const max = { p: 0, val: 0 } | |
| return range(game.width).some(i => { | |
| const value = (game.board[i] || [])[j] | |
| if (value && value === max.p) max.val++ | |
| else max.p = value, max.val = 1 | |
| return max.p && max.val >= game.win | |
| }) | |
| }) | |
| const diagonalNW = range(game.width + game.height - 1).some(k => { | |
| // taking top and left edge | |
| let i = k < game.width ? k : 0 | |
| let j = k < game.width ? 0 : k - game.width + 1 | |
| const max = { p: 0, val: 0 } | |
| while(i < game.width && j < game.height) { | |
| const value = (game.board[i] || [])[j] | |
| if (value && value === max.p) max.val++ | |
| else max.p = value, max.val = 1 | |
| if (max.p && max.val >= game.win) return true | |
| i++, j++ | |
| } | |
| }) | |
| const diagonalNE = range(game.width + game.height - 1).some(k => { | |
| // taking top and right edge | |
| let i = k < game.width ? k : game.width - 1 | |
| let j = k < game.width ? 0 : k - game.width + 1 | |
| const max = { p: 0, val: 0 } | |
| while(i >= 0 && j < game.height) { | |
| const value = (game.board[i] || [])[j] | |
| if (value && value === max.p) max.val++ | |
| else max.p = value, max.val = 1 | |
| if (max.p && max.val >= game.win) return true | |
| i--, j++ | |
| } | |
| }) | |
| return verticalEnd || horizontalEnd || diagonalNW || diagonalNE | |
| } | |
| function print() { | |
| console.log('\x1B[2J\x1B[0f') // Clear screen | |
| // x index | |
| console.log([' '].concat(range(game.width)).join(' ')); | |
| range(game.height).map(j => { | |
| console.log( | |
| j + ' ', // y index | |
| range(game.width).map(i => coin[(game.board[i] || [])[j] || 0] ).join(' ') | |
| ) | |
| }) | |
| console.log('') | |
| } | |
| function place(i, j, p) { | |
| if (isNaN(i) || isNaN(j)) return false | |
| if (i < 0 || i > game.width - 1) return false | |
| if (j < 0 || j > game.height - 1) return false | |
| if (p < 1) return false | |
| if (!game.board[i]) game.board[i] = [] | |
| if (game.board[i][j]) return false | |
| return game.board[i][j] = p | |
| } | |
| const game = { | |
| board: [], | |
| width: 3, | |
| height: 3, | |
| win: 3, | |
| } | |
| let currentPlayer = 1; | |
| while(!end()) { | |
| print() | |
| let i, j | |
| do { | |
| const inp = readLineSync(`Player "${coin[currentPlayer]}" (x y):`) | |
| const split = inp.split(',').length < 2 ? inp.split(' ') : inp.split(',') | |
| i = parseInt(split[0]), j = parseInt(split[1]) | |
| } while(!place(i, j, currentPlayer) && (console.log('Invalid move'), true)) | |
| currentPlayer++ | |
| if (currentPlayer > 2) currentPlayer = 1 | |
| } | |
| print() | |
| console.log(`\nGame over. Player "${coin[currentPlayer]}" won.\n`) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment