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 값이 같을때만 눌리는 구먼 호호 재밌었다.

//로직 맛있었습니다. 야미~!