본문 바로가기
개발/Javascript

[js] 자바스크립트로 틱택토 구현하기 (ft. e.target.value, forEach)

by 코딩하는 갓디노 2020. 12. 22.

 

자바스크립트를 이용하여,
틱택토(Tic Tac Toe) 게임을 구현하는 예제입니다.

 

예제는 인프런의 제로초, "조현영"님의 강의를 들으면서 공부한 내용입니다.

 

순서도

 

css 코드

<style>
  table {
    border-collapse: collapse;
  }

  td {
    width: 60px;
    height: 60px;
    border: 1px solid #666;
    font-size: 30px;
    text-align: center;
  }
</style>

 

순수 자바스크립트 코드

<script>
  //테이블 화면 구성
  //이차원 배열 만들기-현재 클릭한 위치를 찾기 위해
  let table = document.createElement('table');
  let row = []; //이차원 배열
  let col = []; //이차원 배열
  let turn = 'X'; //턴
  //클릭 콜백함수
  //e.target: 클릭된 요소, e.target.parentNode: 클릭된 요소의 부모 태그
  let clickFn = function(e) {
    e.target;
    //console.log(e.target); //칸
    //console.log(e.target.parentNode); //줄

    //중요. 몇줄 몇칸인지 찾는 방법 indexOf(e.target) <- 클릭한 요소의 index를 찾아줌
    let rowNo = row.indexOf(e.target.parentNode);
    console.log('줄번호', rowNo);
    let colNo = col[rowNo].indexOf(e.target);
    console.log('칸번호', colNo);

    //빈칸인지 아닌지
    if (col[rowNo][colNo].textContent !== "") { //빈칸이 아닐 경우 
      console.log('다른 칸을 클릭하세요.');
    } else { //빈칸이면
      col[rowNo][colNo].textContent = turn; //턴 체크
      //위치 중요(턴 패스하기 전)
      //3줄 빙고 확인
      let bingo = false;
      //가로줄 검사
      if (col[rowNo][0].textContent === turn &&
        col[rowNo][1].textContent === turn &&
        col[rowNo][2].textContent === turn) {
        bingo = true;
      }

      //세로줄 검사
      if (col[0][colNo].textContent === turn &&
        col[1][colNo].textContent === turn &&
        col[2][colNo].textContent === turn) {
        bingo = true;
      }

      //대각선 검사 //좌상->우하 대각선 검사
      if (rowNo - colNo === 0 || Math.abs(rowNo - colNo) === 2) {
        if (col[0][0].textContent === turn &&
          col[1][1].textContent === turn &&
          col[2][2].textContent === turn) {
          bingo = true;
        }
        if (col[0][2].textContent === turn &&
          col[1][1].textContent === turn &&
          col[2][0].textContent === turn) {
          bingo = true;
        }
      }

      //빙고일 경우 //bingo = true
      if (bingo) {
        result.textContent = `WINNER는 ${turn}님 축하드립니다`;
        //초기화
        turn = 'X';
        //배열의 반복문 forEach - 이차원 배열이므로 forEach 2번 필요
        col.forEach(function(row) {
          row.forEach(function(td) {
            td.textContent = '';
          });
        });
      } else { //빙고가 안되었으면
        if (turn === 'X') {
          turn = 'O';
        } else {
          turn = 'X';
        }
      }
    }
  }

  for (let i = 0; i < 3; i += 1) {
    let tr = document.createElement('tr');
    //이차원 배열
    row.push(tr);
    col.push([]);
    for (let j = 0; j < 3; j += 1) {
      let td = document.createElement('td');
      td.addEventListener('click', clickFn);
      tr.appendChild(td);
      //중요
      col[i].push(td); //이차원 배열 완성
    }
    table.appendChild(tr);
  }
  document.body.append(table);
  let result = document.createElement('div');
  document.body.append(result);
</script>

 

전체 코드

<!DOCTYPE html>
<html lang="ko">

<head>
    <meta charset="UTF-8">
    <title>틱택토</title>
    <style>
        table {
            border-collapse: collapse;
        }

        td {
            width: 60px;
            height: 60px;
            border: 1px solid #666;
            font-size: 30px;
            text-align: center;
        }
    </style>
</head>

<body>
    <script>
        let table = document.createElement('table');
        let row = []; //이차원 배열
        let col = []; //이차원 배열
        let turn = 'X'; //턴
      
        let clickFn = function(e) {
            e.target;
            //console.log(e.target); //칸
            //console.log(e.target.parentNode); //줄

            let rowNo = row.indexOf(e.target.parentNode);
            console.log('줄번호', rowNo);
            let colNo = col[rowNo].indexOf(e.target);
            console.log('칸번호', colNo);
            
            if (col[rowNo][colNo].textContent !== "") { //빈칸이 아닐 경우 
                console.log('다른 칸을 클릭하세요.');
            } else { //빈칸이면
                col[rowNo][colNo].textContent = turn; //턴 체크
                let bingo = false;
                //가로줄 검사
                if (col[rowNo][0].textContent === turn &&
                    col[rowNo][1].textContent === turn &&
                    col[rowNo][2].textContent === turn) {
                    bingo = true;
                }

                //세로줄 검사
                if (col[0][colNo].textContent === turn &&
                    col[1][colNo].textContent === turn &&
                    col[2][colNo].textContent === turn) {
                    bingo = true;
                }

                //대각선 검사 //좌상->우하 대각선 검사
                if (rowNo - colNo === 0 || Math.abs(rowNo - colNo) === 2) {
                    if (col[0][0].textContent === turn &&
                        col[1][1].textContent === turn &&
                        col[2][2].textContent === turn) {
                        bingo = true;
                    }
                    if (col[0][2].textContent === turn &&
                        col[1][1].textContent === turn &&
                        col[2][0].textContent === turn) {
                        bingo = true;
                    }
                }

                if (bingo) {
                    result.textContent = `WINNER는 ${turn}님 축하드립니다`;
                    //초기화`
                    turn = 'X';
                    col.forEach(function(row) {
                        row.forEach(function(td) {
                            td.textContent = '';
                        });
                    });
                } else { 
                    if (turn === 'X') {
                        turn = 'O';
                    } else {
                        turn = 'X';
                    }
                }
            }
        }

        for (let i = 0; i < 3; i += 1) {
            let tr = document.createElement('tr');
            row.push(tr);
            col.push([]);
            for (let j = 0; j < 3; j += 1) {
                let td = document.createElement('td');
                td.addEventListener('click', clickFn);
                tr.appendChild(td);
                col[i].push(td);
            }
            table.appendChild(tr);
        }
        document.body.append(table);
        let result = document.createElement('div');
        document.body.append(result);
    </script>
</body>

</html>

 

forEach() ***

· 배열의 반복문 배열의 반복문 
· 주어진 콜백함수를 배열 요소 각각에 대해 실행
· 콜백함수를 받아옴

const food = ['🍕', '🥨', '🥪', '🍔'];
food.forEach(function(ele, index) {
    console.log(ele, index);
});
//결과
🍕 0
🥨 1
🥪 2
🍔 3

food.forEach(function(ele) {
    console.log(ele);
});
//결과
🍕
🥨
🥪
🍔

 

arrow 함수 표현

food.forEach((ele, index) => console.log(ele, index));

 

이차원 배열의 forEach() 사용법

Array.forEach(function(row) {
    row.forEach(function(td) {
    	td.textContent = '';
    });
  });

 

틱택토 예제

 

event.target / event.currentTarget

  • 이벤트가 일어난 것이 누구인지를 알 수 있습니다. 
  • 주로 이벤트 중 클릭한 대상 요소를 가져오는 방법으로 event 객체의 target 또는 currentTarget property를 사용합니다. 

event.target
실제 이벤트가 발생한 대상
이벤트 버블링의 가장 마지막에 위치한 최하위 요소를 반환합니다. 


event.currentTaget: 
이벤트를 적용시킨 대상
이벤트가 바인딩된 요소, 해당하는 요소를 반환합니다. 

<div id="clickBox">
	<span>click</span>
</div>

<script>
  document.getElementById('clickBox').addEventListener('click', function(event) {
  	let target = event.target;
  	let currentTarget = event.currentTarget;
  	console.log(target);
    
  	console.log(currentTarget);
  });
</script>

div 내부 span 태그를 클릭한 경우 결과

event.target: 
//<span>click</span> 
event.currentTarget: 
//<div id="clickBox"> 
	<span>click</span> 
  </div>

 

화면 결과(Result 클릭)

반응형

댓글