2021.05.14
소스코드: mine-sweeper.html
기본적으로 좌클릭을 했을 때랑 우클릭을 했을 때를 나눠서 처리해야 한다.


상태값에 따른 코드를 정의할 때 보통 숫자로 지정하는데 여러 번 시뮬레이션을 한 뒤에 최적의 숫자조합을 찾는 것이 현명하다.
코드숫자는 0~8까지 열린 칸
지뢰가 없을 때 닫힌 칸(NORMAL)은 -1, 물음표칸(QUESTION)은 -2, 깃발 칸(FLAG)은 -3.
지뢰가 있을 때 닫힌 칸은(MINE) -4, 물음표칸(QUESTION_MINE)은 -5, 깃발 칸(FLAG_MINE)은 -6
candidate에 빈 공간을 만들고 그 공간에 0부터 99까지 채워넣는다.mine갯수인 10개를 뺀 공간에 랜덤으로 채워넣는다.이차원 배열로 rowData배열에 CODE.NORMAL(-1)을 채워넣는다.랜덤하게 생성된 지뢰 칸 위치(shuffle[k])에 MINE(-6)을 data[][]에채워넣는다.onRightClick함수 생성 후 preventDefault로 기본동작 제거. target으로 html코드 불러올 수 있음.$tbody.addEventListener("contextmenu", onRightClick);에서 contextmenu는 우클릭이벤트인데 해당 이벤트 콜백을 onRightClick으로 적용.onLeftClick()을 선언 후 닫힌 칸인지 지뢰칸(지뢰칸이면 removeEventListener.)인지 여부 판단 함.countMine()도 정의해서 주변 지뢰갯수를 카운트한다.openAround(), isNormal(), open()을 정의해서 open이 0이면 openAround가 주변을 열어준다.100칸 중에 10칸을 제외한 90칸을 모두 열면 승리하는 조건 추가하면 된다.row,cell,mine변수에 input으로 submit할 수 있도록 세팅. submit하면 openCount초기화, tbody지우고 drawTable()실행, timer시작. –> 해당하는 변수들을 let으로 수정.?.
.?는 존재하지 않아도 괜찮은 대상에만 사용해야 한다.if (data[-1]) {
data[-1][-1];
}
이런 식으로 커버할 수 있으며, 또는 접근자 . 앞에 ?를 붙이면 조건접근이 가능하다.
mines.includes(data[rowIndex - 1]?.[cellIndex - 1]) && i++;obj?.prop;
obj?.[expr];
arr?.[index];
func?.(args);
.연산자는 nullish참조값일 때 에러를 뱉고 ?.연산자는 에러 대신 undefined를 리턴하는 차이가 있다.let aProp = obj.first?.second;
obj.first.second에 접근하기 전에 obj.first가 nullish가 아니라는 것을 암묵적으로 확인했다는 뜻이다. 만약 obj.first가 nullish라면 그 표현식은 자동으로 잘리고 undefined가 반환된다. 추가로 아래와 같이 풀어낼 수 있다. (참고:MDN)
let aProp =
obj.first === null || obj.first === undefined
? undefined
: obj.first.second;
??, ||, &&를 추가로 설명하면 기존에 and, or처럼 판단을 해왔지만 엄밀히 논리적으로 따지면 아래와 같다.
재귀할 때 자주 나오는 오류 중 하나.
최대 호출 스택 사이즈를 초과했다는 의미. 호출 스택의 관점으로 봐야한다.
OnLeftClick()위에 openAround()가 여러 개가 얹어지면서 호출만 하고 끝나지 않는 상황이 발생하여 호출 스택의 사이즈를 넘어간다.
그럴 땐 비동기 코드로 감싸주고(setTimeout() 등) 백그라운드와 태스크 큐에 할당하면 된다.