Last active
August 3, 2019 21:27
-
-
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 ¯\_(ツ)_/¯
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
// 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