개발 TIL

퍼즐 만들기 메인 페이지 추가

문미새 2025. 2. 19. 00:02
728x90

설치한 tailwind를 사용하여 스타일 구성을 변경하고, 기존의 게임 페이지는 /game 경로로 이동시켰다.

프로젝트가 실행될 때 메인 페이지에는 닉네임, 퍼즐 개수, 퍼즐 선택 입력을 추가하고 게임 시작 버튼 클릭 시 /game 페이지로 이동하도록 구현했다.

현재 퍼즐 이미지는 3개를 넣어놨는데, 화질과 가독성이 떨어지는 부분이 있어 나중에 깔끔한 퍼즐로 변경할 예정이다.

 

내용을 입력하고 게임시작을 누르면 alert창이 뜨며 확인 버튼을 누르면 game 페이지로 이동한다.

 

이동 시 입력한 닉네임을 확인할 수 있으며, 이동 횟수와 시간, 물음표가 보인다.

  const handleDrop = (event: React.DragEvent<HTMLDivElement>) => {
    event.preventDefault();
    if (draggingPiece === null || changePiece === null) return;

    const newPieces = [...pieces];
    const draggedIndex = pieces.findIndex((p) => p.id === draggingPiece.id);

    const previousPieceIndex = newPieces[draggedIndex].originalIndex;
    const currentPieceIndex = newPieces[changePiece].originalIndex;

    if (previousPieceIndex !== currentPieceIndex) {
      [newPieces[draggedIndex], newPieces[changePiece]] = [
        newPieces[changePiece],
        newPieces[draggedIndex],
      ];

      setMoveCount((prev) => prev + 1);
    }

    setPieces(newPieces);
    setDraggingPiece(null);
    setChangePiece(null);

    setTimeout(() => {
      if (newPieces.every((piece, index) => piece.originalIndex === index)) {
        setIsCompleted(true);
        alert("퍼즐을 완성했습니다!");
      }
    }, 500);
  };

이동 횟수는 퍼즐이 다른 위치로 이동했을 때만 카운트 될 수 있게 이전 위치와 이동한 위치를 비교해서 다를 때만 카운트되게 작성했다.

그리고 모든 퍼즐이 원래 위치로 갔을 때 0.5초 후 퍼즐을 완성했다는 alert창이 뜨며 타이머가 멈춘다.

 

  // /game page 코드
  useEffect(() => {
    if (isCompleted) return;

    const interval = setInterval(() => {
      setSeconds((prev) => prev + 1);
    }, 1000);

    return () => clearInterval(interval);
  }, [isCompleted]);
  
  // timer.tsx 코드
  type TimerProps = {
  seconds: number;
};

const Timer = ({ seconds }: TimerProps) => {
  const minutes = Math.floor(seconds / 60);
  const formattedSeconds = seconds % 60;

  return (
    <p className="text-lg font-semibold">
      {String(minutes).padStart(2, "0")}분{" "}
      {String(formattedSeconds).padStart(2, "0")}초
    </p>
  );
};

export default Timer;

타이머는 game페이지로 접근하면 useEffect로 시간이 흐르도록 작성했다.

 

물음표는 클릭 시 모달 방식으로 퍼즐 원본 이미지를 확인할 수 있다.

type ImgProps = {
  imgSrc: string | null;
  onClose: () => void;
};

const ImgModal = ({ imgSrc, onClose }: ImgProps) => {
  return (
    <div
      className="fixed inset-0 flex items-center justify-center bg-black bg-opacity-70"
      onClick={onClose}
    >
      <img
        src={imgSrc || ""}
        alt="puzzle"
        className="w-full h-full max-w-[80%] max-h-[80%] object-contain"
        onClick={(e) => e.stopPropagation()}
      />
    </div>
  );
};
export default ImgModal;

퍼즐을 완성 시 alert이 뜨는 걸 확인할 수 있다.

 

이 후 목표로는 퍼즐이 완성되면 기록을 등록할 건지 여부를 판단하고 랭킹 페이지로 이동하려고 하고, 랭킹 페이지까지 완성이 되면 이제 수파베이스를 이용해 nosql로 서버를 연동하고 배포까지 학습할 예정이다.

 

tailwind를 자유롭게 쓰기엔 클래스명을 잘 몰라서 한동안 지피티에 좀 의존해야 하지만, 어떤 방식으로 구현하는진 학습했고, 클래스명도 기존 스타일 코드의 단축형이라 금방 적응할 순 있을 것 같다.

728x90