일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 |
- googleColaboratory
- 거북이 대포 게임
- JS 개념
- react
- Spring-Framework
- node.js로 로그인하기
- props
- 리액트
- 모던자바스크립트
- 타자 게임 만들기
- 인프런
- 자바스크립트
- ReactDOM.render is no longer supported in React 18. Use createRoot instead
- You are importing createRoot from "react-dom" which is not supported. You should instead import it from "react-dom/client"
- 웹 게임을 만들며 배우는 리액트
- node.js 설치
- intllij 내 Bean을 찾지 못해서 발생하는 오류
- vs code 내 node
- intellij
- DB Browser
- Concurrently
- spring-boot
- Python
- 노드에 리액트 추가하기
- Colaboratory 글자 깨짐
- 따라하며 배우는 노드 리액트 기본 강의
- 모두의 파이썬
- react오류
- Do it 자바스크립트 + 제이쿼리 입문
- 계산맞추기 게임
- Today
- Total
프로그래밍 삽질 중
Let's Get IT 자바스크립트 프로그래밍 - 틱택토게임, 컴퓨터랑 하기 본문
* 출처 : https://thebook.io/080270/part02/ch09/
* 이차원 그리기
- 배열 안에 배열이 들어가 있는 형태
//5(줄) × 4(칸) 이차원 배열을 만들어 보세요. 배열의 요소는 모두 1로 만듭니다.
const rows = []; //들어갈 자리
for (let i = 1; i < 6; i++) {//행
const cells = [];
for (let j = 1; j < 5; j++) {//열
cells.push(1);
}
rows.push(cells);
}
console.log(rows);
//결과
//0: (4) [1, 1, 1, 1]
//1: (4) [1, 1, 1, 1]
//2: (4) [1, 1, 1, 1]
//3: (4) [1, 1, 1, 1]
//4: (4) [1, 1, 1, 1]
* push()와 append() 차이점
- push() : 배열의 끝에 하나 이상의 요소 추가, 배열의 새로운 길이 반환(기존 배열 값 변경)
* 출처 : https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/push
- append() : element의 마지막 자식 다음에 Node 개체 또는 문자열 개체 집합을 삽입, String 객체는 text 노드로 삽입
(원문 : The Element.append() method inserts a set of Node objects or string objects after the last child of the Element. String objects are inserted as equivalent Text nodes.)
* 출처 : https://developer.mozilla.org/en-US/docs/Web/API/Element/append
- 개인적 생각 : push는 배열의 값 추가에 주로 사용하고 append는 javascript에서 값 요소에 새로운 개체를 추가할 때 사용
* 삼항연산자
- 맨 앞에 조건문 그 뒤에 물음표(?) 조건은 참 콜론(:)은 거짓
- 출처 : https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Operators/Conditional_Operator
function actor(name) {
return (name === 'TOM CRUISE' ? 'TOP GUN : MAVERICK' : 'THOR: LOVE & THUNDER')
}
console.log(actor('TOM CRUISE')); //"TOP GUN : MAVERICK"
console.log(actor('CHRIS HEMSWORTH')); // "THOR: LOVE & THUNDER"
* 이벤트 버블링
- event.target이 바뀌지 않으면 자식 태그에서 클릭한 일이 부모 태그에서도 동일하게 적용
- 이벤트 버블링에 대한 자세한 내용 : https://ko.javascript.info/bubbling-and-capturing
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>이벤트 버블링</title>
</head>
<body>
<header>
<div>
<button>클릭</button>
</div>
</header>
<script>
//버튼을 클릭할 때 'hello, event bubbling'을 alert 하게 다음 코드를 수정하세요.
//단, 이벤트 리스너를 button 태그에 달아서는 안 됩니다.
document.querySelector('header').addEventListener('click', () => {
console.log('hello, evnt bubbling - header tag');
})
</script>
</body>
</html>
* 틱택토에서 승자 확인
- 가로가 연속되게 'O' 혹은 'X'
- 세로가 연속되게 'O' 혹은 'X'
- 대각선([0][0], [1][1], [2][2] 나 [0][2], [1][1], [2][0])이 연속되게 'O' 혹은 'X'
const checkWinner = (target) => {
/* 1번 방법
let rowIndex;
let cellIndex;
rows.forEach((row, ri) => {
row.forEach((cell, ci) => {
if (cell === target) {
rowIndex = ri;
cellIndex = ci;
}
});
});
*/
//2번 방법
let rowIndex = target.parentNode.rowIndex;
let 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;
}
* 무승부인 경우
- flat() : flat 메서드는 배열의 차원을 낮추는 메서드로, n차원 배열을 n-1차원 배열로 낮춤,
이차원 배열이라면 일차원 배열로 바뀜
- every() : 배열 안의 모든 요소가 주어진 판별 함수를 통과하는지 테스트, 하나라도 틀리면 false 다 같으면 true
- some() : 배열 안의 모든 요소가 주어진 판별 함수를 통과하는지 테스트, 하나라도 통과도면 true
let draw = rows.flat().every((cell) => cell.textContent);
if (draw) {
$result.textContent = '무승부';
return;
}
* 틱택토 게임 전체 코드
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>틱택토 게임</title>
<style>
table {
border-collapse: collapse;
}
td {
border: 1px solid black;
width: 40px;
height: 40px;
text-align: center;
}
</style>
</head>
<body>
<script>
//예시
//[
// ['', 'O', 'X']
// ['', 'X', 'O']
// ['', 'O', 'X']
//]
const { body } = document;
const $table = document.createElement('table');
const $result = document.createElement('div'); //결과창
const rows = [];
let turn = 'O';
//승부확인
const checkWinner = (target) => {
/* 1번 방법
let rowIndex;
let cellIndex;
rows.forEach((row, ri) => {
row.forEach((cell, ci) => {
if (cell === target) {
rowIndex = ri;
cellIndex = ci;
}
});
});
*/
let rowIndex = target.parentNode.rowIndex;
let 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;
}
//클릭할 때 'O', 'X' 들어가게 하기
const callback = (event) => {
if (event.target.textContent !== '') {
console.log('빈 칸이 아닙니다.')
return;
} else {
console.log('빈 칸 입니다.');
event.target.textContent = turn;
const hasWinner = checkWinner(event.target);
//승자가 있는 경우
if (hasWinner) {
$result.textContent = `${turn}님이 승리!`;
$table.removeEventListener('click', callback);
return;
};
//무승부라면
let draw = rows.flat().every((cell) => cell.textContent);
if (draw) {
$result.textContent = '무승부';
return;
}
//승자가 없는 경우
turn = turn === 'X' ? 'O' : 'X';
}
}
for (let i = 1; i < 4; i++) {
const $tr = document.createElement('tr');
const cells = [];
for (let j = 1; j < 4; j++) {
const $td = document.createElement('td');
$tr.append($td);
cells.push($td);
}
rows.push(cells);
$table.append($tr);
$table.addEventListener('click', callback);
//td값으로 들어가나 이벤트 버블링으로 td <- tr <- table에서 동일한 이벤트 발생
}
body.append($table);
body.append($result);
</script>
</body>
</html>
* 처음 'O'는 사람이 다음 번 'X'는 컴퓨터가 1초 뒤에 실행되게 하기 + 컴퓨터 누를 때는 사용자가 누를 수 없음
- filter() : 는 요소를 순회하며 인수로 넣은 함수의 반환값이 true가 되는 요소만 걸러냄
- 중복되는 요소(빈칸 클릭, 이겼는지 졌는지, 무승부인지, 결과가 나지 않았으면 'O', 'X' 반복)는 함수로 분리
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>틱택토 게임</title>
<style>
table {
border-collapse: collapse;
}
td {
border: 1px solid black;
width: 40px;
height: 40px;
text-align: center;
}
</style>
</head>
<body>
<script>
//예시
//[
// ['', 'O', 'X']
// ['', 'X', 'O']
// ['', 'O', 'X']
//]
const { body } = document;
const $table = document.createElement('table');
const $result = document.createElement('div'); //결과창
const rows = [];
let turn = 'O';
let clickable = true; //컴퓨터가 동작 시 사람이 누르지 못하게 함
//승부확인
const checkWinner = (target) => {
let rowIndex = target.parentNode.rowIndex;
let 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) => { //사람이 하는 것과 컴푸터가 하는 것 중복
const hasWinner = checkWinner(target);
//승자가 있는 경우
if (hasWinner) {
$result.textContent = `${turn}님이 승리!`;
$table.removeEventListener('click', callback);
return;
};
//무승부라면
let draw = rows.flat().every((cell) => cell.textContent);
if (draw) {
$result.textContent = '무승부';
return;
}
//승자가 없는 경우
turn = turn === 'X' ? 'O' : 'X';
}
//클릭할 때 'O', 'X' 들어가게 하기
const callback = (event) => {
if (!clickable) return; //false면 시작 못하게 함
if (event.target.textContent !== '') {
console.log('빈 칸이 아닙니다.')
return;
} else {
console.log('빈 칸 입니다.');
event.target.textContent = turn;
checkWinnerAndDraw(event.target);
if (turn === 'X') {
clickable = false;
setTimeout(() => {
const emptyCells = rows.flat().filter((v) => !v.textContent);
const randomCell = emptyCells[Math.floor(Math.random() * emptyCells.length)];
randomCell.textContent = 'X';
checkWinnerAndDraw(event.target);
clickable = true;
}, 1000);
}
}
}
for (let i = 1; i < 4; i++) {
const $tr = document.createElement('tr');
const cells = [];
for (let j = 1; j < 4; j++) {
const $td = document.createElement('td');
$tr.append($td);
cells.push($td);
}
rows.push(cells);
$table.append($tr);
$table.addEventListener('click', callback);
//td값으로 들어가나 이벤트 버블링으로 td <- tr <- table에서 동일한 이벤트 발생
}
body.append($table);
body.append($result);
</script>
</body>
</html>
'과거 프로그래밍 자료들 > Javascript&typescript' 카테고리의 다른 글
slice, concat, forEach + 원본을 바꾸는 매서드, 바꾸지 않는 매서드 (0) | 2022.07.20 |
---|---|
Let's Get IT 자바스크립트 프로그래밍 - 텍스트 RPG (0) | 2022.07.20 |
Let's Get IT 자바스크립트 프로그래밍 - 반응속도 테스트, 상위 5개만 보여주기 (0) | 2022.07.14 |
Let's Get IT 자바스크립트 프로그래밍 - 계산기 만들기, 연속 계산 추가 (0) | 2022.07.07 |
Let's Get IT 자바스크립트 프로그래밍 - 끝말잇기, 쿵쿵따 만들기(개념 추가) (0) | 2022.07.06 |