Notice
Recent Posts
Recent Comments
Link
돈이 만드는 세상
틱택토 게임 - zerocho 2021ES 강의 본문
createElement한 것이 실제 화면에 보이지 않더라도 미리 이벤트리스너를 달 수 있습니다
const arr = [1, 2, 3, 4, 5];
const one = arr[0];
const two = arr[1];
const three = arr[2];
const four = arr[3];
const five = arr[4];
const [one, two, three, four, five] = arr;
const [one,, three, five] = arr;
const { body } = document; // === const body = document.body;, 구조분해 할당이라고 불림.
const obj = {
a : 'hello',
b: {
c: 'hi',
d: { e: 'wow' },
},
};
const {a, b: {c, d: {e}}} = opj;
const a = obj.a;
const c = obj.a.c;
const e = obj.b.d.e;
여기서 특징은 모든 친구들에게 구조분해 할당이 되는 것이 아니라 말단 친구들에게만 할당이 된다는 것이다. 여기서는 a, c, e만 할당되었다.
const {a, b} = obj;
const {d: {e}} = b;
이 문제를 해결하기 위해서는 구조분해를 여러 번해서 해결하는 방법이 있다. 구조분해 할당하면 안 돌아가는 친구들이 있으므로 주의하자.
이벤트 버블링
removeEventLisner는 프로그램이 종료될 때 붙혀주는 게 좋다. 끝나기 전까지는 return으로 막는게 좋다. 이벤트 버블링이란 td의 클릭이벤트가 발생시 tr로 올라가고 table로 body로 올라간다. 즉, 이벤트가 부모태그 따라서 올라가는 것이다.
document.querySelector('header').addEventLisner('click', () => {
console.log('button 태그를 클릭해도 이벤트 버블링에 의해서 작동하게 됨.');
});
event.target은 이벤트를 발생시킨 태그에 가리킨다. 그렇다면 진짜 table을 호출하고 싶다면 어떡해야 하는가? -> event.currentTarget을 이용하면 된다. currentTarget은 이벤트리스너를 붙힌 친구를 가리킨다.
이벤트 버블링 현상을 막을라면 어떡해야 하는가? -> event.stopPropagation()을 사용하면 된다.
이벤트 캡쳐링
이벤트 버블링과 반대 현상이다. 부모 태그에서 자식 태그로 가는 현상이다.
자바스크립트 코드
rows.flat().every((td) => td.textContent) // 모든 td의 textContent가 존재하는가?
// false
rows.flat().some((td) => td.textContent) // td 중 단 한개라도 textContent가 존재하는가?
// true
flat()은 2차원 배열을 1차원 배열로 만들어준다. 이 방식은 상위 배열에도 똑같이 적용된다. 3->2->1로 가기 위해 flat()을 두번 사용하면 된다.
자바스크립트 코드
const { body} = document; // === const body = document.body;, 구조분해 할당이라고 불림.
const $result = document.createElement('div');
const $table = document.createElement('table');
const rows = [];
let clickable = true;
let turn = 'O';
const checkWinner = (target) => {
const rowIndex = target.parentNode.rowIndex;
const cellIndex = target.cellIndex;
// 세칸 다 채워졌나?
let hasWinner = false;
// 가로 줄 검사
if(
rows[rowIndex][0].textContent === turn &&
rows[rowIndex][1].textContent === turn &&
rows[rowIndex][2].textContent === turn
) {
hasWinner = true;
}
// 세로줄 검사
if(
rows[0][cellIndex].textContent === turn &&
rows[1][cellIndex].textContent === turn &&
rows[2][cellIndex].textContent === turn
) {
hasWinner = true;
}
// 대각선 검사
if(
rows[0][0].textContent === turn &&
rows[1][1].textContent === turn &&
rows[2][2].textContent === turn
) {
hasWinner = true;
}
if(
rows[0][2].textContent === turn &&
rows[1][1].textContent === turn &&
rows[2][0].textContent === turn
) {
hasWinner = true;
}
// 무승부 검사
return hasWinner;
};
const checkWinnerAndDraw = (target) => {
// 승부 판단하기
if(checkWinner(target)) {
$result.textContent = `축하드립니다. ${turn}님이 승리하셨습니다`;
$table.removeEventListener('click', callback);
return;
}
// 무승부 검사
const draw = rows.flat().every((cell) => cell.textContent);
if(draw) {
$result.textContent = `아쉽게도 무승부입니다.`;
return;
}
turn = (turn === 'O' ? 'X' : 'O');
};
const callback = (event) => {
// 칸에 글자가 있나?
if(!clickable) return;
if(event.target.textContent) return;
event.target.textContent = turn;
checkWinnerAndDraw(event.target);
if(turn === 'X') {
const emptyCells = rows.flat().filter((v) => !v.textContent);
const randomCell = emptyCells[Math.floor(Math.random() * emptyCells.length)];
clickable = false;
setTimeout(() => {
randomCell.textContent = 'X';
checkWinnerAndDraw(randomCell);
clickable = true;
}, 1000);
}
};
for(let i = 0; i < 3; i++) {
const $tr = document.createElement('tr');
const cells = [];
for(let j = 0; j < 3; j++) {
const $td = document.createElement('td');
cells.push($td);
$tr.append($td);
}
$table.append($tr);
rows.push(cells);
}
$table.addEventListener('click', callback);
body.append($table);
body.append($result);
전체 코드
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>틱택토</title>
<style>
table {
border-collapse: collapse;
}
td {
border: 1px solid black;
width: 40px;
height: 40px;
text-align: center;
}
</style>
</head>
<body>
<!-- <table>
<tr>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
</tr>
</table> -->
<script>
const { body} = document; // === const body = document.body;, 구조분해 할당이라고 불림.
const $result = document.createElement('div');
const $table = document.createElement('table');
const rows = [];
let clickable = true;
let turn = 'O';
const checkWinner = (target) => {
const rowIndex = target.parentNode.rowIndex;
const cellIndex = target.cellIndex;
// 세칸 다 채워졌나?
let hasWinner = false;
// 가로 줄 검사
if(
rows[rowIndex][0].textContent === turn &&
rows[rowIndex][1].textContent === turn &&
rows[rowIndex][2].textContent === turn
) {
hasWinner = true;
}
// 세로줄 검사
if(
rows[0][cellIndex].textContent === turn &&
rows[1][cellIndex].textContent === turn &&
rows[2][cellIndex].textContent === turn
) {
hasWinner = true;
}
// 대각선 검사
if(
rows[0][0].textContent === turn &&
rows[1][1].textContent === turn &&
rows[2][2].textContent === turn
) {
hasWinner = true;
}
if(
rows[0][2].textContent === turn &&
rows[1][1].textContent === turn &&
rows[2][0].textContent === turn
) {
hasWinner = true;
}
// 무승부 검사
return hasWinner;
};
const checkWinnerAndDraw = (target) => {
// 승부 판단하기
if(checkWinner(target)) {
$result.textContent = `축하드립니다. ${turn}님이 승리하셨습니다`;
$table.removeEventListener('click', callback);
return;
}
// 무승부 검사
const draw = rows.flat().every((cell) => cell.textContent);
if(draw) {
$result.textContent = `아쉽게도 무승부입니다.`;
return;
}
turn = (turn === 'O' ? 'X' : 'O');
};
const callback = (event) => {
// 칸에 글자가 있나?
if(!clickable) return;
if(event.target.textContent) return;
event.target.textContent = turn;
checkWinnerAndDraw(event.target);
if(turn === 'X') {
const emptyCells = rows.flat().filter((v) => !v.textContent);
const randomCell = emptyCells[Math.floor(Math.random() * emptyCells.length)];
clickable = false;
setTimeout(() => {
randomCell.textContent = 'X';
checkWinnerAndDraw(randomCell);
clickable = true;
}, 1000);
}
};
for(let i = 0; i < 3; i++) {
const $tr = document.createElement('tr');
const cells = [];
for(let j = 0; j < 3; j++) {
const $td = document.createElement('td');
cells.push($td);
$tr.append($td);
}
$table.append($tr);
rows.push(cells);
}
$table.addEventListener('click', callback);
body.append($table);
body.append($result);
</script>
</body>
</html>
'프로그래밍 > JavaScript' 카테고리의 다른 글
반응속도 체크 게임 - zerocho ES2021 강의 (0) | 2021.11.04 |
---|---|
객체 다루기_가위바위보 게임- zerocho ES2021 강의 (0) | 2021.11.03 |
숫자야구 코드 및 설명 - zerocho ES2021 강의 (0) | 2021.11.02 |
로또 추첨기 코드 및 로또 뽑기 코드 - zerocho ES 2021 강의 (0) | 2021.11.02 |