자바스크립트 #09 지뢰찾기(우클릭으로 깃발꼽기, 물음표기능, 주변 지뢰갯수 세기)

수박·2020년 6월 10일
0

JavaScript

목록 보기
10/22

자바스크립트 #09 지뢰찾기(우클릭으로 깃발꼽기, 물음표기능, 주변 지뢰갯수 세기)

우클릭을 통해 깃발을 꼽는 기능을 작성합니다.

td에 대해 클릭 이벤트리스너를 등록해야하고, 클릭된 부분을 ! 문자로 변경합니다.

우클릭에 대한 이벤트는 contextmenu이벤트 입니다.

비동기함수로 실행되므로 td를 생성할 때 모든 td객체에 대해 contextmenu 이벤트리스너를 등록해야합니다.

   for(var j = 0; j < hor; j++)
         {
             arr.push(1);
             var td = document.createElement('td');
             td.addEventListener('contextmenu',function(e){
                 e.preventDefault();
                 console.log('event!');
                 //우클릭된 특정행, 열을 찾기위한 인덱스 선언
                 var trParent = e.currentTarget.parentNode;
                 var tbodyParent = e.currentTarget.parentNode.parentNode;
                 //현재 우클릭된 td는 trParent(tr)에 속한 유사배열입니다.
                 //이를 배열의 indexOf메소드를 사용하기 위해 Array.prototype을 사용합니다
                 //https://poiemaweb.com/js-array
                 var col = Array.prototype.indexOf.call(trParent.children, e.currentTarget);
                 var row = Array.prototype.indexOf.call(tbodyParent.children, trParent);
             }
           }

우클릭을 했을 때 클릭이벤트와 마찬가지로 몇번째 행, 몇번째 열인지 알아내는 코드를 작성합니다.

e.currentTarget은 이벤트가 바인딩된 요소를 반환합니다. 여기서 td가 이벤트로 등록되어있으니 td를 가리킵니다.

e.target은 이벤트 버블링 최말단 요소를 반환합니다. 마찬가지로 td가 최말단이므로 td를 가리킵니다.

<div onclick="checkTarget();">
    <span>test</span>
</div>
function checkTarget(event) {
    console.log(event.target); // span을 가리킴
    console.log(event.currentTarget은); // div를 가리킴
} //http://wiki.simuruk.com/index.php/javascript_event.target%EC%99%80_event.currentTarget_%EC%B0%A8%EC%9D%B4?TheOrder=1 출처

배열리터럴 객체리터럴

https://poiemaweb.com/js-array

위의 방식으로 우클릭된 td요소의 행,열위치를 알았으니 이제 이에 대한 처리를 진행합니다.

한번 클릭시 !로 그리고 두번째 클릭에는 ? 다시 클릭했을때 원래의 상태로 돌아오게 만듭니다.

        if(e.currentTarget.textContent === '' || e.currentTarget.textContent === 'X')
                 {
                     e.currentTarget.textContent ='!';
                 }
                 else if(e.currentTarget.textContent === '!')
                 {
                     e.currentTarget.textContent = '?';
                 }
                 else if(e.currentTarget.textContent === '?')
                 {
                     if(dataSet[row][col] === 1)
                        e.currentTarget.textContent = '';
                    else if(dataSet[row][col] === 'X')
                        e.currentTarget.textContent ='X';
                 }

현재 클릭된 곳의 text가 공백이거나 X(지뢰)이면 !로 만들고, 현재 !이면 ?로, 그리고 ?이면 공백이나 지뢰로 만듭니다.

지뢰를 심을때 dataSet의 데이터를 X로 지정해주었고 그렇지 않은 부분은 전부 1로 초기화해두어서 1일때는 공백으로, 그리고 X일때는 X로 그대로 나오게 작성합니다.

주변 지뢰갯수 세기

공백을 클릭했을때 주변 지뢰 갯수를 세고 지뢰를 클릭했을때 '펑'글자로 바꾸도록 합니다.

td에 대한 클릭이벤트리스너를 등록하고 마찬가지로 행,열위치를 찾은 다음, 주변 8칸에 대해서 dataSet이 X인 값들을 카운트해줍니다.

 if(dataSet[row][col] === 'X')
     e.currentTarget.textContent = '펑';
  else
  {
     //해당하는 원소들을 return이 true인 요소만 모아서 그것에 대한 크기를 구한다
     var around = [ dataSet[row][col - 1],dataSet[row][col + 1] ];
     if(dataSet[row - 1])
        around = around.concat(dataSet[row - 1][col - 1],dataSet[row - 1][col], dataSet[row - 1][col + 1]);
     if(dataSet[row + 1])
        around = around.concat(dataSet[row + 1][col - 1],dataSet[row + 1][col],dataSet[row + 1][col + 1]);
      
      var aroundMineCnt = around.filter(function(v)
        {
         return v === 'X';
         }).length;
       //주변에 지뢰가 몇개 있는지 확인
      e.currentTarget.textContent = aroundMineCnt;

around배열은 주변 8칸의 원소들의 값을 갖는 배열입니다.

concat메소드를 통해 기존 배열에 덧붙이는 작업을 진행합니다.

만약 클릭된 위치의 주변 원소중 데이터가 없는 위치, (사각형의 변에 해당하는 위치가 클릭됐을때) dataSet의 윗줄 또는 아랫줄의 데이터가 존재할 때 존재하는 원소들을 덧붙여주는 concat을 수행합니다.

around배열에는 현재 클릭된 위치 주변 8원소의 값들이 존재합니다.

filter메소드를 이용해 원소의 값이 X인 값들의 길이를 구할 수 있습니다.

aroundMineCnt에는 값이 X인 원소들의 갯수를 가지고 있습니다.

이를 통해 현재 클릭된 위치의 주변 8개를 탐색해 주변 지뢰갯수를 화면에 뿌려줄 수 있습니다.

0개의 댓글