ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [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>&nbsp;</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>;
    })}

    위에처럼 짜면 정상적으로 동작한다.

     

     

Designed by Tistory.