Created
May 7, 2018 13:38
-
-
Save bmeck/3ff9ef3b78ab20a556aa9bf8abf2c431 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
<!doctype html> | |
<html> | |
<style> | |
.screenreader-only { | |
position: absolute; | |
display: block; | |
left: -1px; | |
top: -1px; | |
width: 1px; | |
height: 1px; | |
overflow: hidden; | |
} | |
</style> | |
<body> | |
<div aria-hidden>Use a screen reader.</div> | |
<div role="region" class="screenreader-only"> | |
<p> | |
Tick Tac Toe: | |
Use the keyboard to select a location and then place a marker. | |
</p> | |
<div id="scollback" role="log" aria-live="assertive" /> | |
<div id="buttons" /> | |
</div> | |
</body> | |
<script> | |
const locationString = ({row, column}) => { | |
return `row ${row + 1} column ${column + 1}` | |
}; | |
const locationOf = el => ({ | |
row: +el.dataset.row, | |
column: +el.dataset.column, | |
}); | |
const id = ({row, column}) => `button_${row}_${column}`; | |
for (let row = 0; row < 3; row++) { | |
for (let column = 0; column < 3; column++) { | |
const el = document.createElement('button'); | |
Object.assign(el, { | |
id: id({row, column}), | |
type: 'button', | |
textContent: `place on ${locationString({row, column})}` | |
}); | |
Object.assign(el.dataset, {row, column}); | |
buttons.appendChild(el); | |
} | |
} | |
window.onkeydown = e => { | |
const el = document.activeElement; | |
let row = 1, column = 1; | |
if (el === document.body) { | |
switch (e.key) { | |
default: return; | |
case 'ArrowDown': | |
case 'ArrowUp': | |
case 'ArrowLeft': | |
case 'ArrowRight': | |
} | |
} else { | |
[{row, column}] = [locationOf(el)]; | |
if (e.key === 'ArrowDown') { | |
row++; | |
} else if (e.key === 'ArrowUp') { | |
row--; | |
} else if (e.key === 'ArrowLeft') { | |
column--; | |
} else if (e.key === 'ArrowRight') { | |
column++; | |
} | |
} | |
row %= 3; | |
if (row < 0) row += 3; | |
column %= 3; | |
if (column < 0) column += 3; | |
document.getElementById(id({row, column})).focus(); | |
} | |
let turn = 0; | |
let markers = ['X', 'O',]; | |
buttons.onclick = e => { | |
const {row, column} = locationOf(e.target); | |
const current = board[row][column]; | |
if (current !== null) { | |
log(`Cannot place a marker at row ${row + 1} column ${column + 1}. That space is already occupied`); | |
} else { | |
board[row][column] = markers[turn]; | |
if (win()) { | |
log(`${markers[turn]} wins!`); | |
dump(); | |
return; | |
} else if (tie()) { | |
log('Tie Game!'); | |
return; | |
} | |
turn = (turn + 1) % 2; | |
} | |
dump(); | |
}; | |
const board = [ | |
[null,null,null], | |
[null,null,null], | |
[null,null,null] | |
]; | |
let inARow = (a, b, c) => { | |
return a !== null && a === b && a === c; | |
} | |
let win = () => { | |
return ( | |
inARow(board[0][0], board[0][1], board[0][2]) || | |
inARow(board[1][0], board[1][1], board[1][2]) || | |
inARow(board[2][0], board[2][1], board[2][2]) || | |
inARow(board[0][0], board[1][0], board[2][0]) || | |
inARow(board[0][1], board[1][1], board[2][1]) || | |
inARow(board[0][2], board[1][2], board[2][2]) || | |
inARow(board[0][0], board[1][1], board[2][2]) || | |
inARow(board[0][2], board[1][1], board[2][0]) || | |
false | |
); | |
} | |
let tie = () => { | |
let hasEmpty = board.some(row => row.some(column => column === null)); | |
return !hasEmpty; | |
}; | |
const log = msg => { | |
scollback.appendChild(Object.assign(document.createElement('p'), { | |
textContent: msg | |
})); | |
}; | |
const dump = () => { | |
const txt = board.map( | |
(row, i) => { | |
return `row ${i+1}: ${row.map(column => { | |
return column === null ? 'empty': column; | |
}).join(', ')}` | |
} | |
).join('.\n') + '.'; | |
log(`It is ${markers[turn]}'s turn. ${txt}`); | |
console.table(board) | |
} | |
dump(); | |
</script> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment