Skip to content

Instantly share code, notes, and snippets.

@rajaraodv
Last active October 15, 2017 23:23
Show Gist options
  • Save rajaraodv/4513e94dbbbfc4443b7478d4e12f7799 to your computer and use it in GitHub Desktop.
Save rajaraodv/4513e94dbbbfc4443b7478d4e12f7799 to your computer and use it in GitHub Desktop.
Hyperapp version of TicTacToe app
const { h, app } = hyperapp;
/** @jsx h */
function Square(props) {
return (
<button class="square" onclick={props.onClick}>
{props.value}
</button>
);
}
function Board(props) {
const renderSquare = (i) => (
<Square value={props.squares[i]} onClick={() => props.onClick(i)} />
);
return (
<div>
<div class="board-row">
{renderSquare(0)}
{renderSquare(1)}
{renderSquare(2)}
</div>
<div class="board-row">
{renderSquare(3)}
{renderSquare(4)}
{renderSquare(5)}
</div>
<div class="board-row">
{renderSquare(6)}
{renderSquare(7)}
{renderSquare(8)}
</div>
</div>
);
}
function Game({ state, actions }) {
const history = state.history;
const current = history[state.stepNumber];
const winner = calculateWinner(current.squares);
let status;
if (winner) {
status = "Winner: " + winner;
} else {
status = "Next player: " + (state.xIsNext ? "X" : "O");
}
const moves = history.map((step, move) => {
const desc = move ? "Go to move #" + move : "Go to game start";
return (
<li key={move}>
<button
onclick={() => {
actions.jumpTo(move);
}}
>
{desc}
</button>
</li>
);
});
return (
<div class="game">
<div class="game-board">
<Board
squares={current.squares}
onClick={i => actions.handleClick(i)}
/>
</div>
<div class="game-info">
<div>{status}</div>
<div>{moves}</div>
</div>
</div>
);
}
//A central "state" object
const state = {
history: [
{
squares: Array(9).fill(null)
}
],
stepNumber: 0,
xIsNext: true
};
//A central "actions" object. Hyperapp provides fragmented state and actions to prevent any collision
const actions = {
handleClick: (state, actions, i) => {
const history = state.history.slice(0, state.stepNumber + 1);
const current = history[history.length - 1];
const squares = current.squares.slice();
if (calculateWinner(squares) || squares[i]) {
return;
}
squares[i] = state.xIsNext ? "X" : "O";
return {
history: history.concat([
{
squares: squares
}
]),
stepNumber: history.length,
xIsNext: !state.xIsNext
};
},
jumpTo: (state, actions, step) => {
return {
stepNumber: step,
xIsNext: step % 2 === 0
};
}
};
//A central "view" function
const view = (state, actions) => <Game state={state} actions={actions} />;
// ========================================
app({ state, actions, view });
const calculateWinner = squares => {
const lines = [
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[0, 3, 6],
[1, 4, 7],
[2, 5, 8],
[0, 4, 8],
[2, 4, 6]
];
for (let i = 0; i < lines.length; i++) {
const [a, b, c] = lines[i];
if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
return squares[a];
}
}
return null;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment