#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;
}
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(() => {
    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 [score, setScore] = useState(0)
  
  const onWhack = points => setScore(score + points)
  
  return (
    <Fragment>
      {!playing && <h1>Whac a Mole</h1>}
      <button onClick={() => setPlaying(!playing)}>{playing ? 'Stop' : 'Start'}</button>
      {playing &&
        <Fragment>
          <Score value={score} />
          <Timer
            time={TIME_LIMIT}
            onEnd={() => setPlaying(false)}
          />
          <Moles>
            {new Array(NUMBER_OF_MOLES).fill().map((_, index) => (
              <Mole key={index} onWhack={onWhack} />
            ))}
          </Moles>
        </Fragment>
      }
    </Fragment>
  )
}

render(<Game/>, document.getElementById('app'))
View Compiled

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.