24/1/11 스피드게임(speed Game)
2024. 1. 12. 08:43ㆍ카테고리 없음
<SpeedGamePage.jsx> 팀원이 만들어주신 스피드게임 코드분석
import React from "react";
import OneToFifty from "../components/speedGame/OneToFifty";
const SpeedGamePage = () => {
return (
<div>
<OneToFifty /> //요 컴포넌트 하나만 있구먼 흠흠
</div>
);
};
export default SpeedGamePage;
<OneToFifty.jsx>
import React, { useState, useRef } from "react"; //유즈레프랑 유즈 스테이트를 사용하실건가보넹
import styled from "styled-components";
import Board from "./Board"; //요거랑 밑에꺼는 컴포넌트인거 같고
import Timer from "./Timer";
import Swal from "sweetalert2"; //스윗얼럿이군
let array = [];
for (let i = 1; i <= 25; i++) { //1부터 25 number를 담은 배열 이고
array.push(i);
}
function OneToFifty() {
const [numbers, setNumbers] = useState(array); //얘는 위에 배열을 초기값으로 같는구나
const [gameFlag, setGameFlag] = useState(false); //플래그 상태 변화라 false true의 토글인거 같은데?
const [current, setCurrent] = useState(1); //흐름 저장? 초기가 1인거 보니 증가 값인가?
const record = useRef(); //요건 기록용인가?
const handleClick = (num) => { //온클릭함수처럼 보이는구먼
if (num === current && gameFlag) { //num을 매개변수로 받고 그게 현재값과 일치하고
// 성공 시, alert // 게임플레그가 true일때
if (num === 50) { //num 50일때
let timerInterval; //선언만 하셨고
Swal.fire({ //게임 완료한거 알려주고
title: "축하 드립니다 !!!",
html: `완료 기록 : ${record.current / 1000}초`,
timer: 2000,
timerProgressBar: true,
didOpen: () => {
Swal.showLoading(); //요건 스윗얼럿의 용법인거 같은데
},
willClose: () => {
clearInterval(timerInterval); //인터벌함수를 종료하는거 같고
},
}).then((result) => { //오 then이라~ 스윗얼럿을 잘몰라서 결과값 뭐 받는건지 모르겄넹?
if (result.dismiss === Swal.DismissReason.timer) { //암튼 이런게 있구먼
console.log("I was closed by the timer"); //단순 콘솔찍는것보니 별거 아닌거 같고
}
});
// console.log(record.current / 1000);
endGame(); //게임끝내는 함수 같고....
}
const index = numbers.indexOf(num); //위에 넘버스라는 배열에서 num의 인덱스를 찾는구먼
setNumbers((numbers) => [
...numbers.slice(0, index), //배열을 바꾸는데 num을 제외한 그 앞 요소까지의 배열로 바꾸는구먼? 왜지?
num < 26 ? num + 25 : 0, //num의 상태에 따라 숫자형식요소를 하나 더 넣어주고...
...numbers.slice(index + 1), //요거는 배열의 num을 제외한 뒷부분을 다시한번 넣어주는구먼?
]);
setCurrent((current) => current + 1); //current 1증가시켜주고
}
};
const shuffleArray = (array) => { //array 를 매개변수로 바꿔서 array를 return을 하는군
for (let i = array.length - 1; i > 0; i--) { //요거는 i를 줄여나가면서 포문 도는구먼
let j = Math.floor(Math.random() * (i + 1)); //이로직으로 i이하의 랜덤 정수를 구하고 있구먼
[array[i], array[j]] = [array[j], array[i]]; //구조분해로 서로 요소 할당값을 바꾸고
}
return array; //배열의 요소들을 섞는거네
};
const startGame = () => {
setNumbers(shuffleArray(array)); //섞은 어레이로 넘버스 세팅하고
setCurrent(1); //시작 카운트 1로 맞추고
setGameFlag(true); //요거 트루로 하면 게임 시작이구먼
};
const endGame = () => {
setGameFlag(false); //요거 false면 게임 끝이고 흐음
};
return (
<Container>
<StDiv>
{gameFlag ? ( //게임이 시작하면 타이머가 마운트되면서 타이머가 시작하겠구먼
<Timer record={record} />
) : (
<StBtn onClick={startGame}>Start</StBtn> //요건 시작전잉께 스타트 버튼이고
)}
</StDiv>
<Board numbers={numbers} handleClick={handleClick}></Board> //넘버스배열과 핸들클릭함수를 프롭스로
</Container>
);
}
const Container = styled.div`
width: 100%;
height: 500px;
display: flex;
justify-content: center;
align-items: flex-start;
`;
const StDiv = styled.div`
display: flex;
width: 100%;
padding-top: 20px;
justify-content: center;
`;
const StBtn = styled.button` //css는 평범해 보이는구먼
width: 200px;
height: 40px;
margin-top: 50px;
font-size: 30px;
font-weight: bold;
color: white;
background-color: lightpink;
border: none;
box-shadow: 5px 5px 5px grey;
border-radius: 10px;
`;
export default OneToFifty;
<Timer.jsx>타이머는 간단할꺼 같으니까 먼저 볼까용?
import React, { useState, useEffect } from "react";
import styled from "styled-components";
function Timer({ record }) { //record라는 useRef를 프롭스로 받았었군
const [timeElapsed, setTimeElapsed] = useState(0); //시간붕괴? elapse가 머징? ㅇㅋ 일단 통과
record.current = timeElapsed; //useRef에 스테이트 값을 할당이라 이렇게 써본적은 없는데 오호라
useEffect(() => { //역시 마운트와 동시에 발동하는 useEffect가 있구먼
const timer = setInterval(() => { //셋인터벌로 0.03초마다 일어나는구먼
setTimeElapsed((timeElapsed) => timeElapsed + 30); //아하 시간 재는거네
}, 30);
return () => clearInterval(timer); //와 여기 언마운트 로직도 있네 와 나이쓰 USing 이다
}, []);
return (
<Container>
<Time>
{Math.floor(timeElapsed / 1000)} : {(timeElapsed % 1000) / 10} //지나간 시간들을 보여주는거같고
</Time> //초단위로 보이게끔 // 콜론아래는 소수점자리까지 보이게끔 하셨군
</Container>
); //useState는 여기 리랜더링 시켜서 화면 보여줄려고 있던 거구먼?
}
const Container = styled.div`
margin-top: 30px;
width: 100px;
height: 50px;
display: flex;
justify-content: center;
align-items: center;
font-size: 30px;
`;
const Time = styled.div`
position: fixed;
text-align: center;
top: 250px;
width: 100%;
color: darkkhaki;
`;
export default Timer; // 정석 타이머의 느낌이 나서 좋았습니다.
<Board.jsx>
import React from "react";
import styled from "styled-components";
import Cell from "./Cell"; //Cell이라는 컴포넌트 확인
function Board({ numbers, handleClick }) { //역시 이 두개를 프롭스로 받았고
return (
<Container>
{numbers.map((num, index) => (
<Cell num={num} key={index} handleClick={handleClick}></Cell> //단순이 프롭스의 배열을 map함수
))}
</Container> //map함수로 <Cell /> 이라는 태그를 뿌려주는구먼
); //handle 클릭은 한번더 전달하고 흐음 그렇군
}
const Container = styled.div`
width: 400px;
height: 400px;
border: 1px solid blue;
display: grid;
margin-top: 150px;
position: absolute;
grid-template-columns: repeat(5, 1fr); //예쁜 정렬을 위해 그리드를 사용하셨군
grid-template-rows: repeat(5, 1fr);
`;
export default Board;
<Cell.jsx> map함수로 배열의 요소만큼 만들어진 Cell을 봅시당
import React from "react";
import styled from "styled-components";
function Cell({ num, handleClick }) {
return (
<Container onClick={() => handleClick(num)}> //프롭스로 받은 num이랑 클릭함수를 속성에 할당하고
{num !== 0 ? num : null} // 숫자가 0이 아니면 보여주고 0이면 보여주지 말아라라?
</Container>
);
}
const Container = styled.div`
border: 1px solid red;
display: flex;
justify-content: center;
align-items: center;
font-size: 30px;
`;
export default Cell; //흐음 그렇구만
//결론 일딴 이 모든 로직을 확실하게 100% 이해하기 위해서는 이 게임을 한번더 해보고 handleClick 함수를 한번더
//봐야 좋겠지만 클릭하면 배열을 바꾸는데 누른 숫자를 25씩 증가해주고 누른숫자가 26을 넘으면 0이 되는 배열로 만들고
//클릭하는 num 이 50에 도달하면 게임 끝내고 결과 값을 보여주는 구먼
//근데 이게 num이랑 현재카운트인 current 값이 같을때만 눌리는 구먼 호호 재밌었다.
//로직 맛있었습니다. 야미~!