Skip to content

Instantly share code, notes, and snippets.

@hasparus
Last active August 3, 2019 21:27
Show Gist options
  • Save hasparus/f0cec6e8b19bcbdfa9f3bbe0189f17a0 to your computer and use it in GitHub Desktop.
Save hasparus/f0cec6e8b19bcbdfa9f3bbe0189f17a0 to your computer and use it in GitHub Desktop.
I guess this is not really reactive and "svelte-way" but I had fun ¯\_(ツ)_/¯
// https://svelte.dev/repl/65dc3ff369ea423f918e7ac3425b5677?version=3.6.9
<script>
const pipe = (x, ...fs) => fs.reduce((v, f) => f(v), x);
const zip = xs => ys => xs.map((x, i) => [x, ys[i]]);
const head = xs => xs[0];
const filter = predicate => xs => xs.filter(predicate);
const map = predicate => xs => xs.map(predicate);
const tap = proc => x => {
proc(x);
return x;
}
const partition = predicate => xs => {
const noes = [];
const yays = [];
for (const x of xs) {
if (predicate(x)) {
yays.push(x);
} else {
noes.push(x);
}
}
return [noes, yays];
}
const magicSquare = [2, 7, 6, 9, 5, 1, 4, 3, 8]; // https://en.wikipedia.org/wiki/Number_Scrabble
const initialState = {
player: 'x',
cells: new Array(9).fill(''),
};
let state = initialState;
const nextPlayer = player => player === 'x' ? 'o' : 'x';
function mark(i) {
const cells = [...state.cells];
cells[i] = state.player;
const gameWon = pipe(
magicSquare,
zip(cells),
filter(head),
partition(([fst]) => fst === 'x'),
map(map(xs => xs[1])),
tap(console.log),
players => players.some(playerCells => {
for (let i = 0; i < playerCells.length; ++i) {
for (let j = i + 1; j < playerCells.length; ++j) {
for (let k = j + 1; k < playerCells.length; ++k) {
if (playerCells[i] + playerCells[j] + playerCells[k] === 15) {
return true;
}
}
}
}
return false;
})
)
state = gameWon
? { cells, winner: state.player }
: { cells, player: nextPlayer(state.player) }
}
function reset() {
state = initialState;
}
</script>
<main>
{#if state.winner}
<p style="display: inline-block">winner: {state.winner}</p>
<button on:click={reset}>
reset
</button>
{:else}
<p>current player: {state.player}</p>
{/if}
<section class="board">
{#each state.cells as cell, i}
<button class="cell" disabled={Boolean(state.winner || cell)} on:click={() => mark(i)}>
<div class="cell-content">
{cell}
</div>
</button>
{/each}
</section>
</main>
<style>
main {
font-family: monospace;
font-size: 20px;
}
.board {
width: 90vmin;
margin: 0 auto;
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 1fr);
grid-gap: 1em;
}
.cell {
font-size: 3em;
margin: 0;
padding: 0;
background: transparent;
position: relative;
}
.cell-content {
position: absolute;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.cell:after {
content: "";
display: block;
padding-bottom: 100%;
}
.cell:not([disabled]):hover {
background: rgba(0,0,0,0.025)
}
</style>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment