한번 오답했을 시 다시 한번 더 기회를 제공
-checkQuiz, setCheckQuiz를 <ImageGame.js> 파일로 수정
-<Canvas.js>, <Typing.js> 파일에 checkQuiz, setCheckQuiz 상위 컴포넌트로 넘기기
-newFetch 함수 삭제, fetchData 함수로 대체
page - Game - <Canvas.js>
import React, { useEffect, useRef, useState } from "react";
import axios from "axios";
import "../../css/game.css";
function Canvas({
checkAnswer,
fetchData,
quiz,
checkQuiz,
setCheckQuiz,
setAnswerObjButton,
}) {
const canvasRef = useRef(null);
const [isDrawing, setIsDrawing] = useState(false);
const [lastX, setLastX] = useState(0);
const [lastY, setLastY] = useState(0);
const [outputImageSrc, setOutputImageSrc] = useState(null);
const [path, setPath] = useState([]);
const [paths, setPaths] = useState([]);
const [imgText, setImgText] = useState("");
useEffect(() => {
const canvas = canvasRef.current;
const ctx = canvas.getContext("2d");
const drawing = (e) => {
if (!isDrawing) return;
const rect = canvas.getBoundingClientRect();
const offsetX = e.clientX - rect.left;
const offsetY = e.clientY - rect.top;
ctx.beginPath();
ctx.moveTo(lastX, lastY);
ctx.lineTo(offsetX, offsetY);
ctx.strokeStyle = "blue";
ctx.lineWidth = 10;
ctx.stroke();
setLastX(offsetX);
setLastY(offsetY);
setPath((prevPath) => [...prevPath, { x: offsetX, y: offsetY }]);
};
canvas.addEventListener("mousemove", drawing);
return () => {
canvas.removeEventListener("mousemove", drawing);
};
}, [isDrawing, lastX, lastY]);
const drawingCanvas = (e) => {
setIsDrawing(true);
const rect = e.target.getBoundingClientRect();
setLastX(e.clientX - rect.left);
setLastY(e.clientY - rect.top);
setPath([{ x: e.clientX - rect.left, y: e.clientY - rect.top }]);
};
const stopDrawing = () => {
if (isDrawing) {
setPaths((prevPaths) => [...prevPaths, path]);
setPath([]);
}
setIsDrawing(false);
};
const canvasOut = () => {
setIsDrawing(false);
};
const outputCanvasImage = async () => {
const canvas = canvasRef.current;
setOutputImageSrc(canvas.toDataURL());
const dataURL = canvas.toDataURL("image/png");
await axios
.post("http://localhost:5000/canvas", { dataURL: dataURL })
.then((res) => {
setImgText(res.data.text);
checkAnswer(res.data.text);
});
};
const clearCanvas = () => {
const canvas = canvasRef.current;
const ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, canvas.width, canvas.height);
setOutputImageSrc(null);
setPaths([]);
setImgText("");
};
const returnCurrentLine = () => {
setPaths((prevPaths) => prevPaths.slice(0, -1));
};
const redrawCanvas = () => {
const canvas = canvasRef.current;
const ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, canvas.width, canvas.height);
paths.forEach((p) => {
ctx.beginPath();
ctx.moveTo(p[0].x, p[0].y);
for (let i = 1; i < p.length; i++) {
ctx.lineTo(p[i].x, p[i].y);
}
ctx.stroke();
});
};
useEffect(redrawCanvas, [paths]);
const nextLevel = () => {
fetchData();
clearCanvas();
setCheckQuiz(false);
setAnswerObjButton(false);
};
return (
<div className="canvasContainer">
<canvas
ref={canvasRef}
width={500}
height={200}
style={{ border: "1px solid black" }}
onMouseDown={drawingCanvas}
onMouseUp={stopDrawing}
onMouseOut={canvasOut}
/>
<div className="canvasButtonDiv">
{checkQuiz ? (
<div>
<h3>
정답: [{quiz}], 제출한 답: [{imgText}]
</h3>
<button onClick={nextLevel}>다음 레벨</button>
</div>
) : (
<div>
<button onClick={outputCanvasImage}>제출</button>
<button onClick={clearCanvas}>다시 쓰기</button>
<button onClick={returnCurrentLine}>한 획 지우기</button>
</div>
)}
</div>
</div>
);
}
export default Canvas;
page - Game - <Typing.js>
import React, { useState } from "react";
function Typing({
checkAnswer,
quiz,
fetchData,
checkQuiz,
setCheckQuiz,
setAnswerObjButton,
}) {
const [typing, setTyping] = useState("");
const changeTyping = (e) => setTyping(e.target.value);
const sumbitAnswer = () => {
checkAnswer(typing);
};
const nextLevel = () => {
fetchData();
setCheckQuiz(false);
setTyping("");
setAnswerObjButton(false);
};
return (
<div className="typingContainer">
{checkQuiz ? (
<div>
<h3>
정답: [{quiz}], 제출한 답: [{typing}]
</h3>
<button onClick={nextLevel}>다음 레벨</button>
</div>
) : (
<div>
<input value={typing} onChange={changeTyping} />
<button onClick={sumbitAnswer}>제출</button>
</div>
)}
</div>
);
}
export default Typing;
page - Game - <ImageGame.js>
import axios from "axios";
import React, { useEffect, useState } from "react";
import "../../css/game.css";
import Canvas from "./Canvas";
import Typing from "./Typing";
function ImageGame() {
const [imageData, setImagaData] = useState([]);
const [quiz, setQuiz] = useState("");
const [count, setCount] = useState(1);
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 resetButton = () => {
window.location.reload();
};
const changeAnswerObj = () => {
setAnswerObj((answerObj) => !answerObj);
if (answerObjName === "타이핑") {
setAnswerObjName("캔버스");
} else {
setAnswerObjName("타이핑");
}
};
const checkAnswer = (text) => {
if (text === quiz) {
alert("정답입니다.");
setCheckQuiz(true);
setAnswerObjButton(true);
} else {
if (moreChance === 0) { //한번 틀렸을 시
alert("오답입니다. 한 번 더 시도해보세요.");
setMoreChance((moreChance) => moreChance + 1); //오답 횟수 증가
} else if (moreChance === 1) { //두번 틀렸을 시
alert("오답입니다. 다음 라운드로 넘어갑니다.");
setMoreChance(0); //오답 횟수 초기화
setCheckQuiz(true);
setAnswerObjButton(true);
}
}
};
const fetchData = () => {
axios.get("http://localhost:5000/image").then((res) => {
if (res.data.game && res.data.game.length > 0) {
setImagaData(res.data.game[0].image);
setQuiz(res.data.game[0].title);
setCount(res.data.count);
if (count >= 5) {
setGameOver(true);
alert(res.data.message);
}
} else {
setGameOver(true);
alert(res.data.message);
}
});
};
useEffect(() => {
fetchData();
}, []);
return (
<div className="imageGameContainer">
<div className="imageDiv">
{gameOver ? (
<div>
<h1>Game Over</h1>
<button onClick={resetButton}>다시하기</button>
</div>
) : (
<div>
<div className="roundDiv">
<h2>Round: {count} / 5</h2>
<button onClick={changeAnswerObj} disabled={answerObjButton}>
{answerObjName}
</button>
</div>
<img alt="이미지" src={`http://localhost:5000/file/${imageData}`} />
</div>
)}
</div>
{!gameOver && (
<div>
{answerObj ? (
<div>
<Typing
checkAnswer={checkAnswer}
fetchData={fetchData}
quiz={quiz}
checkQuiz={checkQuiz}
setCheckQuiz={setCheckQuiz}
setAnswerObjButton={setAnswerObjButton}
/>
</div>
) : (
<div>
<Canvas
checkAnswer={checkAnswer}
fetchData={fetchData}
quiz={quiz}
checkQuiz={checkQuiz}
setCheckQuiz={setCheckQuiz}
setAnswerObjButton={setAnswerObjButton}
/>
</div>
)}
</div>
)}
</div>
);
}
export default ImageGame;
'프로젝트 > 한글 게임' 카테고리의 다른 글
16. 무작위 나열 (0) | 2024.04.29 |
---|---|
15. 초성/중성/종성 분리 (0) | 2024.04.29 |
13. 캔버스/타이핑 변환 (0) | 2024.04.26 |
12. 캔버스, 이미지 데이터 병합 (0) | 2024.04.22 |
11. 이미지 중복 방지, 횟수 제한 (0) | 2024.04.20 |