ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [JavaScript] 자바스크립트 9강.셀프 체크 - 컴퓨터의 턴 만들기
    Javascript 2023. 6. 8. 18:37
    반응형

    배운 것 정리

    이벤트 버블링

    이벤트 버블링(event)은 이벤트가 발생할 때 부모 태그에도 동일한 이벤트가 발생하는 현상입니다.

     

    parentNode, children

    부모를 찾을거면 parentNode 쓰고 자식을 찾을거면 children를 쓴다.

     

    flat() 함수

    • 유사 배열을 배열로 만들어 준다.
    • 2차원 배열을 1차원으로 만들어 주고 3차원 배열을 2차원으로 만들어준다
    • 3차원 배열을 1차원으로 만들라고 하면 flat을 두 번 쓰면 된다.

    every, some

    • every => 모든 조건이 true이면 true , 하나라도 flase이면 flase
    • some=> 하나만 true이면 true , 모두가 flase이면 flase

     

    문제 요구 사항

    🟦 가장 빠른 다섯 번의 시도를 정렬

    🟦 힌트 sort 메서드 사용🟦 X의 역할은 컴퓨터가 하도록 구현, 무작위칸에 X가 입력되도록 한다.

    🟦 힌트 컴퓨터의 차례는 callback 함수 안에 구현. rows 배열에서 비어있는 칸들 추리기.

    🟦 setTimeout을 이용해 컴퓨터의 턴에 딜레이를 주기

     

    순서도 작성

    1. 시작

    2. 3x3 이차원 배열을 준비한다.

    3. o의 턴으로 설정한다.

    4. 3x3 테이블을 그린다.

    5. 대기

    -----------------------------------

    1. 칸을 클릭한다.

    2. 클릭한 칸이 비어있는가?

    ❌: 대기

    ⭕: 현재 턴을 칸에 적어넣는다.

            승부가 났는가? 🙍‍♂️

            ⭕: 승자를 표시한다. → 끝

            ❌: 무승부인가?

                   ⭕: 무승부라고 표시한다.  끝

                   ❌: 턴을 넘긴다.  컴퓨터의 턴인가?

                                                    ⭕: 빈 공간에 X를 랜덤하게 그린다  🙍‍♂️로 돌아간다

                                                    ❌:  대기

     

     

    정답 코드1 (컴퓨터의 턴 만들기)

    <script>
          const callback = (event) => {
            //칸에 글자가 존재하는지 확인
            if (event.target.textContent !== "") {
              console.log("빈칸이 아닙니다");
              return;
            }
            //글자가 존재하지 않을 때
            console.log("빈칸입니다");
            event.target.textContent = turn;
    
            //승부확인 -> 승자가 있는지 확인
            if (checkWinner(event.target)) {
              $result.textContent = `${turn}님의 승리!`;
              //승리 후 더 이상 클릭되지 않게 이벤트 리스너 제거
              $table.removeEventListener("click", callback);
              return;
            }
            //무승부 검사
            let draw = rows.flat().every((cell) => cell.textContent);
            if (draw) {
              $result.textContent = "무승부";
              return;
            }
    
            //턴 넘기기
            turn = turn === "O" ? "X" : "O";
            if (turn === "X") {
              //filter(조건): 조건에 해당하는 요소들을 걸러준다. 1차원 배열에만 사용가능한 함수.
              const emptyCells = rows.flat().filter((v) => !v.textContent); //td 중 빈칸 추리기
              const randomCell =
                emptyCells[Math.floor(Math.random() * emptyCells.length)];
              randomCell.textContent = "X";
              const hasWinner = checkWinner(randomCell);
              //승자 존재
              if (hasWinner) {
                $result.textContent = `${turn}님의 승리!`;
                return;
              }
              //승자 존재 x
              let draw = rows.flat().every((cell) => cell.textContent);
              if (draw) {
                $result.textContent = "무승부";
                return;
              }
              //턴 넘기기
              turn = turn === "O" ? "X" : "O";
            }
          };
    </script>

    callback 함수에서 새로 추가한 부분은 아래와 같다.

    <script>
          ...
            //턴 넘기기
            turn = turn === "O" ? "X" : "O";
            //이 아래부터 추가
            if (turn === "X") {
              const emptyCells = rows.flat().filter((v) => !v.textContent); //td 중 빈칸 추리기
              const randomCell =
                emptyCells[Math.floor(Math.random() * emptyCells.length)]; //0 ~ emptyCells.length - 1 중 하나를 골라 그 인덱스에 X표시
              randomCell.textContent = "X";
              const hasWinner = checkWinner(randomCell);
              //승자 존재
              if (hasWinner) {
                $result.textContent = `${turn}님의 승리!`;
                return;
              }
              //승자 존재 x
              let draw = rows.flat().every((cell) => cell.textContent);
              if (draw) {
                $result.textContent = "무승부";
                return;
              }
              //턴 넘기기
              turn = turn === "O" ? "X" : "O";
            }
          };
    </script>

    🔆 filter(조건)

    • 조건에 해당하는 요소들을 추려 새로운 배열을 만들어 준다.
    • 1차원 배열에만 사용가능한 함수.(2차원 이상의 배열에 적용하려면 flat() 사용해야 함)

     

    🔆 반복 코드 제거

            승부가 났는가? 🙍‍♂️

            ⭕: 승자를 표시한다. → 끝

            ❌: 무승부인가?

                   ⭕: 무승부라고 표시한다.  끝

                   ❌: 턴을 넘긴다.  컴퓨터의 턴인가?

     

    순서도상 위의 코드 부분이 겹치는 부분. 겹치는 부분은 하나의 함수로 만들어 빼주고 필요한 부분에서 재사용한다. 

          const checkWinnerAndDraw = (target)=>{
            const hasWinner = checkWinner(target)
            //승자 존재 시 
            if (hasWinner) {
              $result.textContent = `${turn}님의 승리!`;
              $table.removeEventListener("click", callback);
              return;
            }
            //승자 존재 x 시
            const draw = rows.flat().every((cell) => cell.textContent);
            if (draw) {
              $result.textContent = "무승부";
              return;
            }
            //턴 넘기기
            turn = turn === "O" ? "X" : "O";
          }

    중복되는 부분을 checkWinnerAndDraw 함수로 빼준다.

          const callback = (event) => {
            //칸에 글자가 존재하는지 확인
            if (event.target.textContent !== "") {
              console.log("빈칸이 아닙니다");
              return;
            }
            //글자가 존재하지 않을 때
            console.log("빈칸입니다");
            event.target.textContent = turn;
    
            //승부확인 -> 승자가 있는지 확인
            checkWinnerAndDraw(event.target);
            if (turn === "X") {
              const emptyCells = rows.flat().filter((v) => !v.textContent); //td 중 빈칸 추리기
              const randomCell =
                emptyCells[Math.floor(Math.random() * emptyCells.length)];
              randomCell.textContent = "X";
              checkWinnerAndDraw(event.target);
            }
          };

    checkWinnerAndDraw 함수를 이용해 callback 함수를 다시 작성하면 위와 같다.

     

    결과화면1 (컴퓨터의 턴 만들기)

    정답 코드2 (조금 똑똑한 컴퓨터 만들기)

          let clickable = true; //컴퓨터 턴 보호 플래그 변수
          const callback = (event) => {
            if (!clickable) return;
            ...
            //승부확인 -> 승자가 있는지 확인
            checkWinnerAndDraw(event.target);
            if (turn === "X") {
              clickable = false; //컴퓨터 턴일 때는 사용자가 클릭 불가
              setTimeout(() => {
                const emptyCells = rows.flat().filter((v) => !v.textContent); //td 중 빈칸 추리기
                const randomCell =
                  emptyCells[Math.floor(Math.random() * emptyCells.length)];
                randomCell.textContent = "X";
                checkWinnerAndDraw(event.target);
                clickable = true; //컴퓨터 턴이 끝나면 사용자가 클릭 가능
              }, 1000);
            }
          };

    위 코드에서 구현한 기능

    • setTimeout을 이용해 1초 뒤에 컴퓨터 턴 코드가 실행되도록 하기
    • clickable 플래그 변수를 사용해 컴퓨터 턴 도중에는 사용자의 클릭이 먹히지 않게 하기
    •  

    결과화면2 (생각하는 척하는 컴퓨터 만들기)

     

    영상 참고

    https://tinyurl.com/49t6j7sy

     

    반응형

    댓글

Designed by Tistory.