24/1/5 tic tac toe( 틱택토 )
2024. 1. 8. 08:29ㆍ카테고리 없음
<TicTacToe.jsx>
import React from "react";
import TicTacToeGame from "../components/TicTacToe/TicTacToeGame";
export default function TicTacToe() {
return (
<>
<TicTacToeGame />
</>
);
}
<TicTacToeGame.jsx>
import React, { useRef, useState } from "react";
import circle from "../../assets/images/circle.png";
import cross from "../../assets/images/cross.png";
import styled from "styled-components";
let data = ["", "", "", "", "", "", "", "", ""]; //틱택토 ox가 들어갈 자리들이 총9개 빈 문자열로 시작한다.
export default function TicTacToeGame() {
let [count, setCount] = useState(0); //총 카운트를 세줄 로직
let [lock, setLock] = useState(false); //각 요소를 잠가놓을지 풀어놓을지 결정한다.
let titleRef = useRef(null);
let box1 = useRef(null); //useRef를 생성해 게임의 타이틀과 각 박스들을 참조할수 있게 세팅
let box2 = useRef(null);
let box3 = useRef(null);
let box4 = useRef(null);
let box5 = useRef(null);
let box6 = useRef(null);
let box7 = useRef(null);
let box8 = useRef(null);
let box9 = useRef(null);
let boxArray = [box1, box2, box3, box4, box5, box6, box7, box8, box9]; //각 박스의태그들을 요소로갖는 배열
const toggle = (e, num) => { // event와 숫자를 매개변수로 갖는다.
if (lock) { // 락상태라면 0 반환
return 0;
}
if (count % 2 === 0) { //락상태가아니고 카운트가 짝수이면 event가 발생하는 태그를
e.target.innerHTML = `<img src='${cross}'>`; //cross이미지를 갖는 태그로 바꾼다.
data[num] = "x"; //data 배열에 해당 num을 인덱스로 갖는 요소를 x로한다.
setCount(++count); //카운트 증가
} else {
e.target.innerHTML = `<img src='${circle}'>`;
data[num] = "o";
setCount(++count); //x의 케이스와 동일하다.
}
checkWin(); //토글함수 마지막에 승자가 있는지 확인
};
const checkWin = () => { //승자확인로직
if (data[0] === data[1] && data[1] === data[2] && data[2] !== "") { //가로 세로 대각선 줄이 한줄안이 빈문자열이
won(data[2]); //아니면 승자 발생
} else if (data[3] === data[4] && data[4] === data[5] && data[5] !== "") {
won(data[5]); //해당 data배열의 해당 인덱스의요소는
} else if (data[6] === data[7] && data[7] === data[8] && data[8] !== "") { //x나 o의 스트링을 갖는다.
won(data[8]);
} else if (data[0] === data[3] && data[3] === data[6] && data[6] !== "") {
won(data[6]);
} else if (data[1] === data[4] && data[4] === data[7] && data[7] !== "") {
won(data[7]);
} else if (data[2] === data[5] && data[5] === data[8] && data[8] !== "") {
won(data[8]);
} else if (data[0] === data[4] && data[4] === data[8] && data[8] !== "") {
won(data[8]);
} else if (data[0] === data[1] && data[1] === data[2] && data[2] !== "") { //뭐지 이제보니 얘 왜 하나 더있지? ㅋ
won(data[2]);
} else if (data[2] === data[4] && data[4] === data[6] && data[6] !== "") {
won(data[6]);
}
};
const won = (winner) => {
setLock(true); //Lock을 true로 만든다.
if (winner === "x") { //위에서 data[i]를 매개변수로 받아서 'x'인지 'o'인지 확인하여 title을 태그를 변경한다.
titleRef.current.innerHTML = `축하합니다 <img src=${cross}> 승리 !`;
} else {
titleRef.current.innerHTML = `축하합니다 <img src=${circle}> 승리 !`;
}
};
const reset = () => { //게임 초기화 로직
setLock(false); //lock을 false로 만들고
data = ["", "", "", "", "", "", "", "", ""]; //'x'나 'o'가 들어 있는 배열을 처음 상태로 만든다.
titleRef.current.innerHTML = `Tic Tac Toe <span>게임</span>`; //title태그를 처음처럼 만든다.
boxArray.map((e) => {
e.current.innerHTML = ""; //맵함수를 돌며 해당 태그들도 빈값으로 만든다.
});
};
return (
<>
<Container>
<Title ref={titleRef}>Tic Tac Toe 게임</Title> //ref속성에 useRef를 선언해둔 변수를 담아서 해당태그 참조
<Board>
<Row1>
<Boxs
ref={box1}
onClick={(e) => { //온클릭시 토글 이벤트 발생
toggle(e, 0);
}}
></Boxs>
<Boxs
ref={box2}
onClick={(e) => {
toggle(e, 1);
}}
></Boxs>
<Boxs
ref={box3}
onClick={(e) => {
toggle(e, 2);
}}
></Boxs>
</Row1>
<Row2>
<Boxs
ref={box4}
onClick={(e) => {
toggle(e, 3);
}}
></Boxs>
<Boxs
ref={box5}
onClick={(e) => {
toggle(e, 4);
}}
></Boxs>
<Boxs
ref={box6}
onClick={(e) => {
toggle(e, 5);
}}
></Boxs>
</Row2>
<Row3>
<Boxs
ref={box7}
onClick={(e) => {
toggle(e, 6);
}}
></Boxs>
<Boxs
ref={box8}
onClick={(e) => {
toggle(e, 7);
}}
></Boxs>
<Boxs
ref={box9}
onClick={(e) => {
toggle(e, 8);
}}
></Boxs>
</Row3>
</Board>
<ResetButton
onClick={() => {
reset();
}}
>
Reset
</ResetButton>
</Container>
</>
);
}
const Container = styled.section`
text-align: center;
`;
const Title = styled.div`
margin-top: 50px;
color: white;
font-size: 60px;
display: flex;
justify-content: center;
align-items: center;
text-shadow: -5px 5px #ffa732, 0px 5px #ffa732, 1px 0px #ffa732,
0px -1px #ffa732;
margin-bottom: 30px;
gap: 30px;
& img {
height: 50px;
}
`;
const ResetButton = styled.button`
width: 250px;
border: none;
outline: none;
cursor: pointer;
border-radius: 50px;
background: var(--yellow);
font-size: 26px;
color: white;
margin-bottom: 50px;
`;
const Boxs = styled.div`
display: flex;
height: 180px;
width: 180px;
background: var(--green);
border: 4px solid white;
cursor: pointer;
& img {
margin: 30px 30px;
}
`;
const Board = styled.div`
height: 600px;
width: 564px;
display: flex;
margin: auto;
`;
const Row1 = styled.div``;
const Row2 = styled.div``;
const Row3 = styled.div``;