본문 바로가기
프로젝트/한글 게임

19. 종성 ' ' 제외, 쉼표(,) 추가

by 갱생angel 2024. 6. 7.

<추가/수정 사항>

※낱말 조합 게임에서 받침이 없는 단어일 시 종성 ' ' 제외하고 랜덤 나열

※각 낱말마다 쉼표(,)를 붙혀 구분, 마지막 낱말은 쉼표(,) 제외

 

Game - <CombineGame.js>

import axios from "axios";
import React, { useCallback, useEffect, useState } from "react";
import "../../css/game.css";
import Canvas from "../../component/Canvas";
import Typing from "../../component/Typing";
import { CHO, JUNG, JONG } from "../../component/Word";
import { useNavigate } from "react-router-dom";

function CombineGame() {
  const navigate = useNavigate();

  const winNum = 1; //서버로 보낼 점수 1점
  const [charArray, setCharArray] = useState([]); //랜덤 문자 배열
  const [quiz, setQuiz] = useState(""); //제시된 텍스트 퀴즈
  const [round, setRound] = useState(1); //라운드
  const [score, setScore] = useState(0); //점수
  const [gameOver, setGameOver] = useState(false); //게임 끝 여부
  const [checkQuiz, setCheckQuiz] = useState(false); //정답, 오답 확인
  const [moreChance, setMoreChance] = useState(0); //재도전 제공
  const [answerObj, setAnswerObj] = useState(false); //캔버스, 타이핑 변환
  const [answerObjName, setAnswerObjName] = useState("타이핑"); //캔버스, 타이핑 변환 버튼 이름
  const [answerObjButton, setAnswerObjButton] = useState(false); //캔버스, 타이핑 변환 버튼

  //초성, 중성, 종성 분리
  const separateText = () => {
    const result = [];
    for (let char of quiz) {
      const unicode = char.charCodeAt(0) - 44032;
      const choIndex = parseInt(unicode / 588);
      const jungIndex = parseInt((unicode - choIndex * 588) / 28);
      const jongIndex = parseInt(unicode % 28);
      const choChar = CHO[choIndex];
      const jungChar = JUNG[jungIndex];
      const jongChar = JONG[jongIndex];
      result.push(choChar, jungChar, jongChar);
    }
    return result;
  };

  const resetButton = () => window.location.reload();

  const checkTrue = () => {
    setCheckQuiz(true);
    setAnswerObjButton(true);
  };

  const toggleAnswerObj = () => {
    setAnswerObj((answerObj) => !answerObj);
    setAnswerObjName((prev) => (prev === "타이핑" ? "캔버스" : "타이핑"));
  };

  const checkAnswer = (text) => {
    if (text === quiz) {
      alert("정답입니다.");
      checkTrue();
      setScore((score) => score + 10);
    } else {
      if (moreChance === 0) {
        alert("오답입니다. 한 번 더 시도해보세요.");
        setMoreChance((moreChance) => moreChance + 1);
      } else if (moreChance === 1) {
        alert("오답입니다. 다음 라운드로 넘어갑니다.");
        setMoreChance(0);
        checkTrue();
      }
    }
  };

  const fetchData = async () => {
    try {
      await axios.get("http://localhost:5000/game").then((res) => {
        if (res.data.game && res.data.game.length > 0) {
          setQuiz(res.data.game[0].title);
          setRound(res.data.count);
          if (round >= 5) {
            setGameOver(true);
            alert(res.data.message);
          }
        } else {
          setGameOver(true);
          alert(res.data.message);
        }
      });
    } catch (err) {
      console.error(err);
    }
  };

  const updateScore = useCallback(async () => {
    const token = localStorage.getItem("token");
    const headerData = {
      headers: {
        Authorization: `Bearer ${token}`,
      },
      withCredentials: true,
    };
    try {
      await axios.post(
        "http://localhost:5000/combineScore",
        { combineScore: winNum },
        headerData
      );
    } catch (err) {
      if (err.response.status === 401) {
        try {
          const refreshRes = await axios.post(
            "http://localhost:5000/refresh",
            {},
            { withCredentials: true }
          );
          const newToken = refreshRes.data.token;
          localStorage.setItem("token", newToken);
          axios.defaults.headers.common["Authorization"] = `Bearer ${newToken}`;
          updateScore();
        } catch (err) {
          console.error(err);
          localStorage.removeItem("token");
        }
      } else {
        console.error(err);
        localStorage.removeItem("token");
      }
    }
  }, [winNum]);

  useEffect(() => {
    fetchData();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  useEffect(() => {
    setCharArray(
      separateText()
        .sort(() => Math.random() - 0.5)
        .filter((char) => char !== "") //종성 '' 제외
    );
    //eslint-disable-next-line react-hooks/exhaustive-deps
  }, [quiz]);

  useEffect(() => {
    if (score >= 50 && localStorage.getItem("token")) updateScore();
  }, [score, updateScore]);

  return (
    <div className="combineGameContainer">
      <div className="combineDiv">
        {gameOver ? (
          <div>
            <h1>Game Over, 점수: {score} / 50</h1>
            <button onClick={resetButton}>다시하기</button>
            <button onClick={() => navigate("/")}>홈으로</button>
          </div>
        ) : (
          <div>
            <div className="roundDiv">
              <h2>Round: {round} / 5</h2>
              <button onClick={toggleAnswerObj} disabled={answerObjButton}>
                {answerObjName}
              </button>
            </div>
            <div className="textQuizDiv">
              <span>{charArray.join(", ")}</span> <!--쉼표(,)로 구분-->
            </div>
          </div>
        )}
      </div>
      {!gameOver && (
        <div>
          {answerObj ? (
            <Typing
              checkAnswer={checkAnswer}
              fetchData={fetchData}
              quiz={quiz}
              checkQuiz={checkQuiz}
              setCheckQuiz={setCheckQuiz}
              setAnswerObjButton={setAnswerObjButton}
            />
          ) : (
            <Canvas
              checkAnswer={checkAnswer}
              fetchData={fetchData}
              quiz={quiz}
              checkQuiz={checkQuiz}
              setCheckQuiz={setCheckQuiz}
              setAnswerObjButton={setAnswerObjButton}
            />
          )}
        </div>
      )}
    </div>
  );
}

export default CombineGame;

'프로젝트 > 한글 게임' 카테고리의 다른 글

20. 난이도 분류  (0) 2024.06.14
18. 초성/중성/종성 파일 모듈화  (0) 2024.05.20
17. 포인트 기능  (0) 2024.05.11
16. 무작위 나열  (0) 2024.04.29
15. 초성/중성/종성 분리  (0) 2024.04.29