-
[team-project_종합 게임 사이트 만들기] 오목 게임 만들기 (1)Project/종합 게임 사이트 2023. 10. 23. 17:55
[ 오늘의 작업 과정 ]
1. 오목판 및 위에 문구 3초 뒤 없어지는 동적인 UI 만들기
2. 오목판에 칸 클릭 시 클릭된 칸 검정색으로 바뀌는 UI 만들기
1. 상단의 글자 3초뒤 없어지는 UI 구현 (Game2.js)
리액트에서 동적인 UI 만드는 3step을 따르면 된다.
먼저 html css 로 미리 UI 디자인을 다 해두고 UI의 현재 상태를 state로 저장해둔 후 state에 따라 UI가 어떻게 보일지 삼항연산자로 작성해줬다.
function Game2() { let [start, setStart] = useState(true); return ( <> <div> {start == true ? <p>* 흑돌 먼저 시작 !</p> : <p> </p>}
여기서 3초 뒤 없어지는 기능인 타이머 기능이 필요하다. 이건 js로 x초후에 코드를 실행하고 싶을 때 사용했던 setTimeout 함수를 사용하면 된다. html 렌더링 이후에 동작하는 코드는 useEffect안에 써주는 것이 유용하다. 반복연산, 타이머 등등.. 컴포넌트 mount(로드)시 1회 실행만 하면 되므로 , 뒤에 []를 써준다. 버그를 방지하기 위해 useEffect에서 타이머 만들기 전에 기존 타이머를 싹 제거하라고 clearTimeout()도 써줬다.
useEffect(() => { let a = setTimeout(() => { setStart(false); }, 3000); return () => { clearTimeout(a); }; }, []);
2. 오목판에 칸 클릭 시 클릭된 칸 검정색으로 바뀌는 기능 구현 (Game2.js)
[ Trouble-Shooting ]
- 문제 1 : 오목판에 각 칸을 클릭하였을 때 한 칸이 아닌 전체 오목판이 검정색으로 변했던 문제
col라는 변수를 만들어 오목판의 각 행의 수 13개를 배열 형태로 저장해뒀고, col 배열에 map 함수를 이용해 중첩시켜 테이블을 만들고 color 라는 state를 만들어 각 칸을 클릭했을 때 black이라는 클래스명이 추가되어 각 칸이 검정으로 바뀌도록 했지만 적용되지 않았다. 문제의 아래 코드이다.. console로 각 칸의 자리를 출력했을 때는 분명 자리값은 (1,1), (12,3)... 이런식으로 각 칸마다 잘 출력되는데 클릭 시 오목판 전체가 검정색으로 바뀐다.
import { useEffect, useState } from "react"; function Game2() { ... 생략 let [color, setColor] = useState(""); var col = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]; return ( <> <div> ... 생략 <table className="tb2"> <tbody> {col.map(function (i) { return ( <tr> {col.map(function (j) { return ( <td className={color} onClick={() => setColor("black") // 클릭시 오목판 전체가 검정으로 변함 // console.log(i,j) // 각 칸의 좌표 정상적으로 출력 } ></td> ); })} </tr> ); })} </tbody> </table> </div> </> ); }
- 해결 과정
클릭된 칸의 좌표의 상태를 담을 state를 만들어 클릭된 칸의 좌표의 초기 state 값은 빈 배열로 지정하고 클릭된 칸의 위치를 배열 안에 담기로 했다. ([1,1] 이런식으로) 그 후 칸을 클릭을 하면 저장되있던 배열의 첫번째 값과 해당 테이블의 i 값이 같고 , 배열의 두번째 값과 j 값이 같으면 칸 색이 변하도록 했다.
function Game2() { var col = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]; var [color, setColor] = useState(''); // 돌의 색상 var [clickedCell, setClickedCell] = useState([]); // 클릭한 칸의 좌표 const handleCellClick = (i,j) => { setClickedCell([i,j]) setColor('black') } return ( <div> <table className="tb2" onClick={() => { }}> <tbody> {col.map(function (i) { return ( <tr> {col.map(function (j) { return <td className={(clickedCell[0] == i && clickedCell[1] == j) ? color : ''} onClick={() => handleCellClick(i,j)}></td>; })} </tr> ); })} </tbody> </table> </div>
결과는 아래와 같다. 이전에 클릭한 칸의 색은 유지되어야 하는데 칸을 누를 때마다 이전의 칸의 색은 지워졌다.,ㅠㅜ
이전의 클릭했던 칸의 좌표값을 저장해둬야 한다. 지금 칸을 누를 때마다 칸의 좌표값이 [1,2] 이런식으로 상태가 변경되므로 누른 좌표값이 [1,2], [2,1] ... 이런식으로 누적되도록 state안에 저장해야 한다. 어떻게 해야할까..?
object 형식으로 [ { i: 1, j : 1}, { i : 1, j : 2 } ... ] 이런식으로 누적해서 저장해보기로 했다.
아래 코드와 같이 클릭했을 때 좌표가 object 형식으로 출력되도록 했다.
var [clickedCell, setClickedCell] = useState([]); // 클릭한 칸의 좌표 const handleCellClick = (i,j) => { setClickedCell([{i,j}]) console.log(clickedCell) }
하지만 object가 누적되서 저장되야하므로 앞에 이전의 좌표값이 들어있는 clickedCell을 넣어주기로 했다. 그냥
[ clickedCell, { i, j} ] 이런식으로 넣다보면 앞에 clickedCell은 array 형태로 추가되기 때문에 겉의 괄호를 없애주는 스프레드 연산자가 필요하다 . 아래 코드와 같이 짜면 정상적으로 좌표값이 object 형태로 누적되어 추가되는 걸 확인할 수 있었다.
var [clickedCell, setClickedCell] = useState([]); // 클릭한 칸의 좌표 const handleCellClick = (i,j) => { setClickedCell([...clickedCell, {i,j}]) console.log(clickedCell) }
다음은 위의 클릭했던 누적된 좌표값과 현재 테이블의 i 값과 j 값이 일치하면 색이 바뀌도록 짜줘야 한다. JS의 some 함수를 사용해서 object 내 원하는 값이 있는지 확인하는 방법을 사용하기로 했다. (참고로 some 함수는 배열 내 원하는 값이 있는지도 확인 가능)
return <td className={ clickedCell.some(e => e.i === i && e.j === j) ? color : '' } onClick={() => handleCellClick(i,j)}></td>; })}
위에처럼 짜면 정상적으로 동작한다.
'Project > 종합 게임 사이트' 카테고리의 다른 글
[team-project_종합 게임 사이트 만들기] 오목 게임 만들기 (5) (0) 2023.11.07 [team-project_종합 게임 사이트 만들기] 오목 게임 만들기 (4) (0) 2023.11.03 [team-project_종합 게임 사이트 만들기] 오목 게임 만들기 (3) (0) 2023.10.29 [team-project_종합 게임 사이트 만들기] 오목 게임 만들기 (2) (0) 2023.10.25 [team-project_종합 게임 사이트 만들기] 게임 별 탭 기능 구현 (0) 2023.10.22