작성
·
194
0
안녕하세요 제로초님
지뢰찾기가 어려워서 쭉 복습중인데, 드디어 조금 갈피가 잡혀서 기쁩니다. 좋은 강의 감사합니다!
수업시간에 따라한 코드리팩토링을 시도해보았어요. 그런데 이벤트단위로 쪼개서 리팩토링을 하는 게 좋을지, 아니면 세세하게 쪼개서 함수로 만들지 고민이 되어요.
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에 속한다
}
//지뢰 심기: 규칙을 찾아서 랜덤숫자의 위치에 지뢰를 배치시키자
지뢰만드는규칙();
});