From 230eff9498668eb5e9548e1273e0a021a3de0129 Mon Sep 17 00:00:00 2001 From: haerong22 Date: Thu, 25 Mar 2021 21:52:18 +0900 Subject: [PATCH] react web game : react router --- react_webgame/{main => 8. 지뢰찾기}/Form.jsx | 0 .../{main => 8. 지뢰찾기}/MineSearch.jsx | 0 react_webgame/{main => 8. 지뢰찾기}/Table.jsx | 0 react_webgame/{main => 8. 지뢰찾기}/Td.jsx | 0 react_webgame/{main => 8. 지뢰찾기}/Tr.jsx | 0 react_webgame/8. 지뢰찾기/client.jsx | 5 + react_webgame/8. 지뢰찾기/index.html | 21 ++++ react_webgame/main/Games.jsx | 20 +++ react_webgame/main/client.jsx | 4 +- react_webgame/main/games/Ball.jsx | 23 ++++ react_webgame/main/games/Lotto.jsx | 78 ++++++++++++ react_webgame/main/games/NumberBaseball.jsx | 83 +++++++++++++ react_webgame/main/games/RSP.jsx | 89 ++++++++++++++ react_webgame/main/games/Try.jsx | 11 ++ react_webgame/main/index.html | 2 +- react_webgame/main/package-lock.json | 115 +++++++++++++++++- react_webgame/main/package.json | 4 +- 17 files changed, 448 insertions(+), 7 deletions(-) rename react_webgame/{main => 8. 지뢰찾기}/Form.jsx (100%) rename react_webgame/{main => 8. 지뢰찾기}/MineSearch.jsx (100%) rename react_webgame/{main => 8. 지뢰찾기}/Table.jsx (100%) rename react_webgame/{main => 8. 지뢰찾기}/Td.jsx (100%) rename react_webgame/{main => 8. 지뢰찾기}/Tr.jsx (100%) create mode 100644 react_webgame/8. 지뢰찾기/client.jsx create mode 100644 react_webgame/8. 지뢰찾기/index.html create mode 100644 react_webgame/main/Games.jsx create mode 100644 react_webgame/main/games/Ball.jsx create mode 100644 react_webgame/main/games/Lotto.jsx create mode 100644 react_webgame/main/games/NumberBaseball.jsx create mode 100644 react_webgame/main/games/RSP.jsx create mode 100644 react_webgame/main/games/Try.jsx diff --git a/react_webgame/main/Form.jsx b/react_webgame/8. 지뢰찾기/Form.jsx similarity index 100% rename from react_webgame/main/Form.jsx rename to react_webgame/8. 지뢰찾기/Form.jsx diff --git a/react_webgame/main/MineSearch.jsx b/react_webgame/8. 지뢰찾기/MineSearch.jsx similarity index 100% rename from react_webgame/main/MineSearch.jsx rename to react_webgame/8. 지뢰찾기/MineSearch.jsx diff --git a/react_webgame/main/Table.jsx b/react_webgame/8. 지뢰찾기/Table.jsx similarity index 100% rename from react_webgame/main/Table.jsx rename to react_webgame/8. 지뢰찾기/Table.jsx diff --git a/react_webgame/main/Td.jsx b/react_webgame/8. 지뢰찾기/Td.jsx similarity index 100% rename from react_webgame/main/Td.jsx rename to react_webgame/8. 지뢰찾기/Td.jsx diff --git a/react_webgame/main/Tr.jsx b/react_webgame/8. 지뢰찾기/Tr.jsx similarity index 100% rename from react_webgame/main/Tr.jsx rename to react_webgame/8. 지뢰찾기/Tr.jsx diff --git a/react_webgame/8. 지뢰찾기/client.jsx b/react_webgame/8. 지뢰찾기/client.jsx new file mode 100644 index 00000000..a8b1eeb2 --- /dev/null +++ b/react_webgame/8. 지뢰찾기/client.jsx @@ -0,0 +1,5 @@ +import React from "react"; +import ReactDom from "react-dom"; +import MineSearch from "./MineSearch"; + +ReactDom.render(, document.querySelector("#root")); diff --git a/react_webgame/8. 지뢰찾기/index.html b/react_webgame/8. 지뢰찾기/index.html new file mode 100644 index 00000000..3257650c --- /dev/null +++ b/react_webgame/8. 지뢰찾기/index.html @@ -0,0 +1,21 @@ + + + + 지뢰찾기 + + + +
+ + + diff --git a/react_webgame/main/Games.jsx b/react_webgame/main/Games.jsx new file mode 100644 index 00000000..e1b80cd6 --- /dev/null +++ b/react_webgame/main/Games.jsx @@ -0,0 +1,20 @@ +import React from "react"; +import { BrowserRouter, HashRouter, Route } from "react-router-dom"; +import NumberBaseBall from "./games/NumberBaseball"; +import RSP from "./games/RSP"; +import Lotto from "./games/Lotto" + +const Games = () => { + + return ( + +
+ + + +
+
+ ); +}; + +export default Games; diff --git a/react_webgame/main/client.jsx b/react_webgame/main/client.jsx index a8b1eeb2..a453f103 100644 --- a/react_webgame/main/client.jsx +++ b/react_webgame/main/client.jsx @@ -1,5 +1,5 @@ import React from "react"; import ReactDom from "react-dom"; -import MineSearch from "./MineSearch"; +import Games from "./Games"; -ReactDom.render(, document.querySelector("#root")); +ReactDom.render(, document.querySelector("#root")); diff --git a/react_webgame/main/games/Ball.jsx b/react_webgame/main/games/Ball.jsx new file mode 100644 index 00000000..a2d2bffd --- /dev/null +++ b/react_webgame/main/games/Ball.jsx @@ -0,0 +1,23 @@ +import React, { memo } from "react"; + +const Ball = memo(({ number }) => { + let background; + if (number <= 10) { + background = "red"; + } else if (number <= 20) { + background = "orange"; + } else if (number <= 30) { + background = "yellow"; + } else if (number <= 40) { + background = "blue"; + } else { + background = "green"; + } + return ( +
+ {number} +
+ ); +}); + +export default Ball; diff --git a/react_webgame/main/games/Lotto.jsx b/react_webgame/main/games/Lotto.jsx new file mode 100644 index 00000000..1877e8b6 --- /dev/null +++ b/react_webgame/main/games/Lotto.jsx @@ -0,0 +1,78 @@ +import React, { + useState, + useRef, + useEffect, + useMemo, + useCallback, +} from "react"; +import Ball from "./Ball"; + +function getWinNumbers() { + console.log("getWinNumbers"); + const candidate = Array(45) + .fill() + .map((v, i) => i + 1); + const shuffle = []; + while (candidate.length > 0) { + shuffle.push( + candidate.splice(Math.floor(Math.random() * candidate.length), 1)[0] + ); + } + const bonusNumber = shuffle[shuffle.length - 1]; + const winNumbers = shuffle.slice(0, 6).sort((p, c) => p - c); + return [...winNumbers, bonusNumber]; +} + +const Lotto = () => { + const lottoNumbers = useMemo(() => getWinNumbers(), []); + const [winNumbers, setWinNumbers] = useState(lottoNumbers); + const [winBalls, setWinBalls] = useState([]); + const [bonus, setBonus] = useState(null); + const [redo, setRedo] = useState(false); + const timeouts = useRef([]); + + useEffect(() => { + runTimeouts(); + return () => { + timeouts.current.forEach((v) => { + clearTimeout(v); + }); + }; + }, [timeouts.current]); + + const runTimeouts = () => { + for (let i = 0; i < winNumbers.length - 1; i++) { + timeouts.current[i] = setTimeout(() => { + setWinBalls((prevBalls) => [...prevBalls, winNumbers[i]]); + }, (i + 1) * 1000); + } + timeouts.current[6] = setTimeout(() => { + setBonus(winNumbers[6]); + setRedo(true); + }, 7000); + }; + + const onClickRedo = useCallback(() => { + setWinNumbers(getWinNumbers()); + setWinBalls([]); + setBonus(null); + setRedo(false); + timeouts.current = []; + }, [winNumbers]); + + return ( + <> +
당첨 숫자
+
+ {winBalls.map((v) => ( + + ))} +
+
보너스
+ {bonus && } + {redo && } + + ); +}; + +export default Lotto; diff --git a/react_webgame/main/games/NumberBaseball.jsx b/react_webgame/main/games/NumberBaseball.jsx new file mode 100644 index 00000000..3b8fe210 --- /dev/null +++ b/react_webgame/main/games/NumberBaseball.jsx @@ -0,0 +1,83 @@ +import React, { useState, useRef, memo } from 'react'; +import Try from './Try'; + +// 숫자 4개를 겹치지않고 랜덤하고 뽑는 함수 +function getNumbers() { + const candidate = [1,2,3,4,5,6,7,8,9]; + const array = []; + for (let i = 0; i < 4; i++) { + const chosen = candidate.splice(Math.floor(Math.random() * (9 - i)), 1)[0]; + array.push(chosen); + } + return array; +} + +const NumberBaseball = memo(() => { + const [result, setresult] = useState(''); + const [value, setvalue] = useState(''); + const [answer, setanswer] = useState(getNumbers()); + const [tries, settries] = useState([]); + const inputRef = useRef(null); + + const onSubmitForm = (e) => { + e.preventDefault(); + if(value === answer.join('')) { // 정답 + setresult('홈런!'); + settries((prevTries) => { + return [...prevTries, { try: value, result: '홈런!'}] + }) + alert('게임을 다시 시작합니다.'); + setvalue(''); + setanswer(getNumbers()); + settries([]); + inputRef.current.focus(); + } else { + const answerArray = value.split('').map((v) => parseInt(v)); + let strike = 0; + let ball = 0 ; + if(tries.length >= 9) { // 10번이상 틀렸을 때 + setresult(`실패! 답은 ${answer.join(',')} 였습니다!`); + alert('게임을 다시 시작합니다.'); + setvalue(''); + setanswer(getNumbers()); + settries([]); + } else { + for (let i = 0; i < 4; i++) { + if(answerArray[i] === answer[i]) { + strike++; + } else if (answer.includes(answerArray[i])) { + ball++; + } + } + settries((prevTries) => { + return [...tries, {try: value, result: `${strike} 스트라이크, ${ball} 볼 입니다.`}] + }) + setvalue(''); + } + inputRef.current.focus(); + } + } + + const onChangeInput = (e) => { + setvalue(e.target.value); + } + + return ( + <> +

{result}

+
+ + +
+
시도: {tries.length}
+
    + {tries.map((v, i) => { + return ( + + ) + })} +
+ + ) +}); +export default NumberBaseball; // import NumberBaseball \ No newline at end of file diff --git a/react_webgame/main/games/RSP.jsx b/react_webgame/main/games/RSP.jsx new file mode 100644 index 00000000..0f855413 --- /dev/null +++ b/react_webgame/main/games/RSP.jsx @@ -0,0 +1,89 @@ +import React, { useState, useRef, useEffect } from "react"; + +const rspCoords = { + 바위: "0", + 가위: "-142px", + 보: "-284px", +}; + +const scores = { + 가위: 1, + 바위: 0, + 보: -1, +}; + +const computerChoice = (imgCoord) => { + return Object.entries(rspCoords).find(function (v) { + return v[1] === imgCoord; + })[0]; +}; + +const RSP = () => { + const [result, setResult] = useState(""); + const [imgCoord, setImgCoord] = useState(rspCoords.바위); + const [score, setScore] = useState(0); + const interval = useRef(); + + useEffect(() => { + // componentDidMount, componentDidUpdate 역할 + // setTimeout(changeHand, 100); + interval.current = setInterval(changeHand, 100); + return () => { + // componentWillUnMount 역할 + clearInterval(interval.current); + }; + }, [imgCoord]); + + const changeHand = () => { + if (imgCoord === rspCoords.바위) { + setImgCoord(rspCoords.가위); + } else if (imgCoord === rspCoords.가위) { + setImgCoord(rspCoords.보); + } else if (imgCoord === rspCoords.보) { + setImgCoord(rspCoords.바위); + } + }; + + const onClickBtn = (choice) => () => { + clearInterval(interval.current); + const myScore = scores[choice]; + const cpuScore = scores[computerChoice(imgCoord)]; + const diff = myScore - cpuScore; + if (diff === 0) { + setResult("비겼습니다!"); + } else if ([-1, 2].includes(diff)) { + setResult("이겼습니다!"); + setScore((prevScore) => prevScore + 1); + } else { + setResult("졌습니다ㅠㅜ"); + setScore((prevScore) => prevScore - 1); + } + setTimeout(changeHand, 2000); + }; + + return ( + <> +
+
+ + + +
+
{result}
+
현재 {score}점
+ + ); +}; + +export default RSP; diff --git a/react_webgame/main/games/Try.jsx b/react_webgame/main/games/Try.jsx new file mode 100644 index 00000000..d5f5ea25 --- /dev/null +++ b/react_webgame/main/games/Try.jsx @@ -0,0 +1,11 @@ +import React, { memo } from 'react'; + +const Try = memo(({ tryInfo }) => { + return ( +
  • +
    {tryInfo.try}
    +
    {tryInfo.result}
    +
  • + ) +}); +export default Try; \ No newline at end of file diff --git a/react_webgame/main/index.html b/react_webgame/main/index.html index 3257650c..a4512fbf 100644 --- a/react_webgame/main/index.html +++ b/react_webgame/main/index.html @@ -1,7 +1,7 @@ - 지뢰찾기 + Games