#app
View Compiled
* {
box-sizing: border-box;
}
:root {
--control: #e69119;
--color: #fff;
}
button {
background: var(--control);
color: var(--color);
padding: 1rem 2rem;
border-radius: 1rem;
border: 4px solid var(--color);
font-family: 'Fredoka One', cursive;
font-size: 1.2rem;
}
body {
background: linear-gradient(#d1e9fa 0 40%, #86c270 40%);
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
font-family: 'Fredoka One', cursive;
}
.end-game {
position: fixed;
top: 1rem;
right: 1rem;
}
import React, { Fragment, useEffect, useRef, useState } from 'https://cdn.skypack.dev/react'
import { render } from 'https://cdn.skypack.dev/react-dom'
const TIME_LIMIT = 30000
const MOLE_SCORE = 100
const NUMBER_OF_MOLES = 5
const Moles = ({ children }) => <div>{children}</div>
const Mole = ({ onWhack }) => (
<button onClick={() => onWhack(MOLE_SCORE)}>Mole</button>
)
const Score = ({ value }) => <div>{`Score: ${value}`}</div>
const Timer = ({ time, interval = 1000, onEnd }) => {
const [internalTime, setInternalTime] = useState(time)
const timerRef = useRef(time)
const timeRef = useRef(time)
useEffect(() => {
if (internalTime === 0 && onEnd) {
onEnd()
}
}, [internalTime, onEnd])
useEffect(() => {
timerRef.current = setInterval(
() => setInternalTime((timeRef.current -= interval)),
interval
)
return () => {
clearInterval(timerRef.current)
}
}, [interval])
return <div>{`Time: ${internalTime / 1000}s`}</div>
}
const Game = () => {
const [playing, setPlaying] = useState(false)
const [finished, setFinished] = useState(false)
const [score, setScore] = useState(0)
const onWhack = points => setScore(score + points)
const endGame = () => {
setPlaying(false)
setFinished(true)
}
const startGame = () => {
setScore(0)
setPlaying(true)
setFinished(false)
}
return (
<Fragment>
{!playing && !finished &&
<Fragment>
<h1>Whac a Mole</h1>
<button onClick={startGame}>Start Game</button>
</Fragment>
}
{playing &&
<Fragment>
<button
className="end-game"
onClick={endGame}
>
End Game
</button>
<Score value={score} />
<Timer
time={TIME_LIMIT}
onEnd={endGame}
/>
<Moles>
{new Array(NUMBER_OF_MOLES).fill().map((_, index) => (
<Mole key={index} onWhack={onWhack} />
))}
</Moles>
</Fragment>
}
{finished &&
<Fragment>
<Score value={score} />
<button onClick={startGame}>Play Again</button>
</Fragment>
}
</Fragment>
)
}
render(<Game/>, document.getElementById('app'))
View Compiled
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.