리팩토링에 관한 질문입니다.

21.01.18 11:10 작성 조회수 117

0

안녕하세요 제로초님

지뢰찾기가 어려워서 쭉 복습중인데, 드디어 조금 갈피가 잡혀서 기쁩니다. 좋은 강의 감사합니다!

수업시간에 따라한 코드리팩토링을 시도해보았어요. 그런데 이벤트단위로 쪼개서 리팩토링을 하는 게 좋을지, 아니면 세세하게 쪼개서 함수로 만들지 고민이 되어요.

  • 질문
  1. 어떤 식이 다시 봤을 때 이해하기 쉬울까요? 
  2. 시도한 리팩토링은 괜찮나요?
var tbody = document.querySelector('#table tbody');
var dataset = [];
var 중단플래그 = false;
var 열은칸 = 0;
var 코드표 = {
    연칸: -1,
    물음표: -2,
    깃발: -3,
    깃발지뢰: -4,
    물음표지뢰: -5,
    지뢰: 1,
    보통칸: 0
};
var 줄;
var 칸;
var 주변;

function 지뢰위치() {
    var 칸채우기 = Array(hor * ver).fill().map(function (인덱스) { //가로 * 세로
        return 인덱스; }); //자바스크립트는 0부터 센다
    var 지뢰만들기 = [];
    while (칸채우기.length > hor * ver - mine) {
      var 지뢰배치표 = 칸채우기.splice(Math.floor(Math.random() * 칸채우기.length), 1)[0];
        지뢰만들기.push(지뢰배치표);
    }
};

function 깃발법칙() {
    if (e.currentTarget.textContent === '' || e.currentTarget.textContent === 'X') { //빈칸이거나 X일 때
        e.currentTarget.textContent = '!'; //깃발과 물음표는 데이터일 필요가 없다. 화면에 표시하는 용도니까
        e.currentTarget.classList.add('flag');
        if (dataset[줄][칸] = 코드표.지뢰) {
            dataset[줄][칸] = 코드표.깃발지뢰;
        } else {
            dataset[줄][칸] = 코드표.깃발;
        }
    } else if (e.currentTarget.textContent === '!') { //느낌표라면
        e.currentTarget.textContent = '?';  //우클릭 한 번은 느낌표, 두 번은 물음표
        e.currentTarget.classList.remove('flag');
        e.currentTarget.classList.add('question');
        if (dataset[줄][칸] = 코드표.깃발지뢰) {
            dataset[줄][칸] = 코드표.물음표지뢰;
        } else {
            dataset[줄][칸] = 코드표.물음표;
        }
    } else if (e.currentTarget.textContent === '?') { //물음표라면
        e.currentTarget.classList.remove('question');
        if (dataset[줄][칸] === 코드표.물음표지뢰) { 
            e.currentTarget.textContent = 'X';
            dataset[줄][칸] = 코드표.지뢰;
        } else {
            e.currentTarget.textContent = '';
            dataset[줄][칸] = 코드표.보통칸;
        }
    }
};

function 오픈법칙() {
    dataset[줄][칸] = 1; //배열 안에 숫자를 넣자(기본설정 = 0)
    var 주변 = [dataset[줄][칸-1], dataset[줄][칸+1]]; //왼쪽, 오른쪽 확인
    if (dataset[줄-1]) { //윗줄 검사
        주변 = 주변.concat([dataset[줄-1][칸-1], dataset[줄-1][칸], dataset[줄-1][칸+1]]);
    } else if (dataset[줄+1]) { //아랫줄 검사
        주변 = 주변.concat([dataset[줄+1][칸-1], dataset[줄+1][칸], dataset[줄+1][칸+1]]);
    }
    var 주변확인 = 주변.filter(function(v) {
        return [코드표.지뢰, 코드표.깃발지뢰, 코드표.물음표지뢰].includes(v); //모든 지뢰를 세자
    }
};

function 주변법칙() {
    if (주변확인 === 0) {
    console.log('주변을 엽니다');
    var 주변칸 = [];
    if (tbody.childre[줄-1]) {
        주변칸 = 주변칸.concat([
            tbdoy.children[줄-1].children[칸-1], tbdoy.children[줄-1].children[칸], tbdoy.children[줄-1].children[칸+1]
        ]);
    if (tbody.childre[줄-1]) {
        주변칸 = 주변칸.concat([
            tbdoy.children[줄].children[칸-1], tbdoy.children[줄].children[칸+1]
        ]);
    if (tbody.childre[줄-1]) {
        주변칸 = 주변칸.concat([
            tbdoy.children[줄+1].children[칸-1], tbdoy.children[줄+1].children[칸], tbdoy.children[줄+1].children[칸+1]
        ]);
    }
    //열려있는 칸을 또 열릴 필요없게 수습하자
    dataset[줄][칸] = 1; //배열 안에 숫자를 넣자(기본설정 = 0)
    주변칸.filter(function(v) {return !!v}).forEach(function(옆칸) {
         //칸 위치 파악
        var 부모tbody = e.currentTarget.parentNode.parentNode;
        var 부모tr = e.currentTarget.parentNode; //몇 줄?
        var 옆칸줄 = Array.prototype.indexOf.call(부모tbody.children, 부모tr); 
        var 옆칸칸 = Array.prototype.indexOf.call(부모tr.children, e.currentTarget); //e.currentTarget = td
        if (dataset[옆칸줄][옆칸칸] !== 코드표.연칸) { 옆칸.click(); }
        });
    }
}
    //지뢰를 제외한 모든 칸이 열리면 승리함
    if (열은칸 === hor * ver - mine) {
        document.querySelector('#result').textContent = '승리하셨습니다~!';
        }
    }
};

function 지뢰만드는규칙() {
    for (var k = 0; k < 지뢰만들기.length; k++) { //배열은 0부터 시작하기에 -1이 나와선 안 된다
        var 세로 = Math.floor(지뢰만들기[k] / ver);
        var 가로 = 지뢰만들기[k] % ver;
        tbody.children[세로].children[가로].textContent = 'X'; //지뢰를 심는다, 화면
        dataset[세로][가로] = 코드표.지뢰; //데이터, 화면과 데이터는 일치해야 됨!
    }
};

//지뢰찾기 실행
document.querySelector('#exec').addEventListener('click', function() { 
    //이전 게임 초기화
    tbody.innerHTML = '';
    document.querySelector('#result').textContent = ''; 
    dataset = [];
    열은칸 = 0;
    중단플래그 = false;

    //input의 아이디들
    var hor = parseInt(document.querySelector('#hor').value); 
    var ver = parseInt(document.querySelector('#ver').value);
    var mine = parseInt(document.querySelector('#mine').value);

    //지뢰위치 
    지뢰위치();

    //지뢰테이블
    for (var i = 0; i < ver; i += 1) { //2차원 배열, 세로 만들기 
        var arr = []; //지뢰표에 배열을 깔자
        var tr = document.createElement('tr');
        dataset.push(arr);
        for (var j = 0; j < hor; j += 1) { //가로 만들기
            arr.push(코드표.보통칸); 
            var td = document.createElement('td');
            //오른쪽 클릭방지
            td.addEventListener('contextmenu', function(e) { 
                e.preventDefault();
                if (중단플래그) { return; }
                //칸 위치 파악
                var 부모tbody = e.currentTarget.parentNode.parentNode;
                var 부모tr = e.currentTarget.parentNode; //몇 줄?
                줄 = Array.prototype.indexOf.call(부모tbody.children, 부모tr); //배열이 아니여도 indexOf()를 쓸 수 있다
                칸 = Array.prototype.indexOf.call(부모tr.children, e.currentTarget); //e.currentTarget = td
                //깃발법칙
                깃발법칙();
                );
            //클릭 시, 주변 지뢰 파악 
            td.addEventListener('click', function(e) {
                if (중단플래그) {
                    return;
                }
                 //칸 위치 파악
                var 부모tbody = e.currentTarget.parentNode.parentNode;
                var 부모tr = e.currentTarget.parentNode; //몇 줄?
                줄 = Array.prototype.indexOf.call(부모tbody.children, 부모tr); //배열이 아니여도 indexOf()를 쓸 수 있다
                칸 = Array.prototype.indexOf.call(부모tr.children, e.currentTarget); //e.currentTarget = td
                if ([코드표.연칸, 코드표.깃발, 코드표.깃발지뢰, 코드표.물음표지뢰, 코드표.물음표].includes(dataset[줄][칸])) { 
                    return;
                }
                //지뢰의 유무확인
                e.currentTarget.classList.add('opend');
                열은칸 += 1;
                if (dataset[줄][칸] === 코드표.지뢰) { 
                    e.currentTarget.textContent = '펑';
                    document.querySelector('#result').textContent = '다시 도전하세요!';
                    중단플래그 = true;
                } else { //지뢰가 없다면 
                    dataset[줄][칸] = 1; //배열 안에 숫자를 넣자(기본설정 = 0)
                    주변 = [dataset[줄][칸-1], dataset[줄][칸+1]]; //왼쪽, 오른쪽 확인
                    오픈법칙().length;
                    e.currentTarget.textContent = 주변확인 || ''; //숫자 0은 표시가 되지 않도록!
                    dataset[줄][칸] = 코드표.연칸;
                    //지뢰없는 부분을 한꺼번에 열리도록 만들자
                    주변법칙();
                    );
            tr.appendChild(td); //td는 tr에 속하고
        }
        tbody.appendChild(tr); //tr은 tbody에 속한다
    }

    //지뢰 심기: 규칙을 찾아서 랜덤숫자의 위치에 지뢰를 배치시키자
    지뢰만드는규칙();
});

답변 2

·

답변을 작성해보세요.

1

함수로 세세하게 쪼개는 것을 추천드립니다. 단 함수로 쪼갤 때는 변수의 스코프 주의하시고요. 매개변수를 활용해 스코프 문제를 해결하시면 됩니다. 그리고 tbdoy 오타 있네요 ㅎㅎ

0

감사합니다~!