자바스크립트 #04 틱택토 검증알고리즘 구현 전

수박·2020년 6월 10일
0

JavaScript

목록 보기
5/22

자바스크립트 #04 틱택토 (2차원배열 , JS동작순서)

JS 동작순서

자바스크립트는 호출스택을 가지고 있다.

호출 스택의 역할은 함수가 실행되면 해당 함수는 호출 스택의 최상단에 위치하게 되고, 함수의 실행이 종료될 때 스택에서 제거하게된다.

이 호출 스택에 쌓이고 빠지고 하는 방식으로 이벤트가 처리되지 않는다. 순서대로 수행되는 동기방식과 그렇지 않은 비동기방식의 이벤트에 차이가 존재한다.

동기방식은 JS엔진이 코드실행중 함수를 발견하면 호출스택에 넣고, 실행하고 종료될 때 스택에서 제거한다.

비동기는 코드 수행중 비동기 이벤트를 발견하면 호출 스택에 넣고, 이벤트 핸들러의 function을 Event Queue에 넣는다.

이때 호출 스택이 비어있으면 Queue에서 호출 스택에 넣고, 수행 후 제거하는 순서로 진행된다.

비동기 이벤트는 JS엔진에 정의되어 있지 않은 함수.

for (var i = 0; i < 3; i++) {
setTimeout(function() {
alert(i);
}, 1000);
}

출처: https://doitnow-man.tistory.com/128 [즐거운인생 (실패 또하나의 성공)]

처음에 해당 코드만 보고 이해가 가지 않았는데 let키워드와 함께보니 이해가 되었다.

setTimeout는 비동기함수이다. 따라서 호출스택에서

동기함수인 for은 먼저 수행한다. for이 종료될때 i값은 전역스코프를 가진 변수이므로 3을 갖고 있는다.

호출스택이 비었으므로 이벤트 큐에서 setTimeout함수를 호출스택으로 넘겨 호출하게 된다.

i는 3인채로 setTimeout이 수행된다.

여기서 var i 대신 let i를 사용하면 문제가 해결된다.

var, let const의 자세한 설명은 참고.

https://poiemaweb.com/es6-block-scope

호이스팅, 스코프, promise 등 아직 와닿지 않,.


이번에 구현할 게임은 틱택토이다.

구글에 틱택토게임을 검색하면 바로 진행할 수 있다.

간단하게 3목이다.

틱택토 FLOWCHART

구현에 필요한 플로우차트이다.

3X3을 만들기 위해서 테이블을 만든다.

table의 tr은 행, td는 열을 의미한다.

따라서 하나의 테이블안에 3개의 tr. 그리고 각 tr마다 3개의 td를 만들어야한다.

var body = document.body;
var table = document.createElement('table');

for(i = 0; i < 3; i++){
    var tr = document.createElement('tr');
    for(j = 0 ; j < 3; j++){
        var td = document.createElement('td');
    tr.appendChild(td);
    }
    table.appendChild(tr);
}
body.appendChild(table);

그렇다면 각 td의 값(X가 들어갈 곳)을 관리하기 위해 이를 2차원배열에 담아야한다.

2차원배열의 선언은 다음과 같이 할 수 있다.

var newArray1 = new Array( new Array(3), new Array(3) );

//직접 선언
 var newArray2 = [[], []];
 newArray[0][0] = 1;
 ...
 ...
 
var newArray3 = Array(Array(), Array());
newArray[0].push(1);
..
..

//반복문을 이용한 2차원 배열
var spaceArr = new Array();
for(i = 0; i < 3; i++)
    spaceArr[i] = new Array();

마지막 방법이 제일 괜찮은 것 같다.

자! 아무튼 이제 각 칸마다 클릭을 했을 때 X의 값을 갖도록 하는 클릭이벤트를 작성해보자

 td.addEventListener('click', callback);

for문에 갹 요소마다 이벤트리스너를 등록을 하고

var callback = function(e)
{
    var rowValue = rowArr.indexOf(e.target.parentNode);

    var colValue = spaceArr[rowValue].indexOf(e.target); 
    console.log(rowValue,colValue);

    if(spaceArr[rowValue][colValue].textContent !== '')//칸이 이미 채워져 있는지?
    {
        console.log("fiiled");
    }
    else
    {
        
        spaceArr[rowValue][colValue].textContent = turn;
        if(turn == 'X')
            turn = 'O';
        else
            turn = 'X';
    }
}

콜백함수를 작성했다.

rowArr는 3개의 행을 갖는 배열이고

spaceArr는 9개의 td값을 갖는 2차원 배열이다.

각 td요소를 클릭했을때마다 행, 열 위치를 알아내기 위해 row, colValue를 작성했다.

rowValue는 rowArr행에서 현재 수행되는 이벤트(e)에 대한 타겟(td)의 부모노드(tr) 객체의 인덱스를 찾아 저장하는 변수이다.

즉 td요소중 하나를 클릭했을 때(이벤트 호출)

이벤트의 타겟은 해당 td가 된다.(e.target)

그리고 그에 대한 부모노드는 td를 포함한 tr이된다(e.target.parentNode)

그렇다면 현재 tr은 rowArr에 선언된 객체중 하나이므로 인덱스를 갖는다. rowArr에서 현재 클릭된 tr의 인덱스를 rowValue에 저장하는 것이다.

마찬가지로

 var colValue = spaceArr[rowValue].indexOf(e.target); 

열의 위치도 알아낼 수 있다.

2차원배열로 선언된 spaceArr의 행위치에서 현재 클릭된 td의 인덱스를 찾는다.

이를 통해 클릭된 요소의 위치가 어느행, 어느열에 위치했는지 알 수 있다.

중간결과

틱택토 중간

0개의 댓글