7 |
10 | Pick 1 or more numbers that sum to the number of stars
11 |
12 |
15 |
31 |
34 |
45 |
56 |
67 |
78 |
89 |
100 |
111 |
122 |
133 |
134 |
135 |
138 | Time Remaining:
139 | 10
140 |
141 |
142 | `;
143 |
--------------------------------------------------------------------------------
/src/components/Game.js:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from 'react';
2 | import utils from '../math-utils';
3 |
4 | import StarsDisplay from './StarsDisplay';
5 | import PlayNumber from './PlayNumber';
6 | import PlayAgain from './PlayAgain';
7 |
8 | const useGameState = () => {
9 | const [stars, setStars] = useState(utils.random(1, 9));
10 | const [availableNums, setAvailableNums] = useState(utils.range(1, 9));
11 | const [candidateNums, setCandidateNums] = useState([]);
12 | const [secondsLeft, setSecondsLeft] = useState(10);
13 |
14 | useEffect(() => {
15 | if (secondsLeft > 0 && availableNums.length > 0) {
16 | const timerId = setTimeout(
17 | () => setSecondsLeft((prevSecondsLeft) => prevSecondsLeft - 1),
18 | 1000
19 | );
20 | return () => clearTimeout(timerId);
21 | }
22 | }, [secondsLeft, availableNums]);
23 |
24 | const setGameState = (newCandidateNums) => {
25 | if (utils.sum(newCandidateNums) !== stars) {
26 | setCandidateNums(newCandidateNums);
27 | } else {
28 | const newAvailableNums = availableNums.filter(
29 | (n) => !newCandidateNums.includes(n)
30 | );
31 | setStars(utils.randomSumIn(newAvailableNums, 9));
32 | setAvailableNums(newAvailableNums);
33 | setCandidateNums([]);
34 | }
35 | };
36 |
37 | return { stars, availableNums, candidateNums, secondsLeft, setGameState };
38 | };
39 |
40 | const Game = (props) => {
41 | const {
42 | stars,
43 | availableNums,
44 | candidateNums,
45 | secondsLeft,
46 | setGameState,
47 | } = useGameState();
48 |
49 | const candidatesAreWrong = utils.sum(candidateNums) > stars;
50 | const gameStatus =
51 | availableNums.length === 0 ? 'won' : secondsLeft === 0 ? 'lost' : 'active';
52 |
53 | const numberStatus = (number) => {
54 | if (!availableNums.includes(number)) {
55 | return 'used';
56 | }
57 |
58 | if (candidateNums.includes(number)) {
59 | return candidatesAreWrong ? 'wrong' : 'candidate';
60 | }
61 |
62 | return 'available';
63 | };
64 |
65 | const onNumberClick = (number, currentStatus) => {
66 | if (currentStatus === 'used' || secondsLeft === 0) {
67 | return;
68 | }
69 |
70 | const newCandidateNums =
71 | currentStatus === 'available'
72 | ? candidateNums.concat(number)
73 | : candidateNums.filter((cn) => cn !== number);
74 |
75 | setGameState(newCandidateNums);
76 | };
77 |
78 | return (
79 |