Skip to content

Instantly share code, notes, and snippets.

@bmeck
Created May 7, 2018 13:38
Show Gist options
  • Save bmeck/3ff9ef3b78ab20a556aa9bf8abf2c431 to your computer and use it in GitHub Desktop.
Save bmeck/3ff9ef3b78ab20a556aa9bf8abf2c431 to your computer and use it in GitHub Desktop.
<!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