JS에서 테이블만들기, 자식태그, 2차원배열, 2차원배열클릭이벤트, forEach

JS에서 테이블만들기, 자식태그, 2차원배열, 2차원배열클릭이벤트, forEach

웹 게임을 만들며 배우는 JS : 틱택토
JS에서 테이블만들기, 자식태그, 2차원배열, 2차원배열클릭이벤트, forEach

1. JS에서 테이블과 HTML태크 만들기

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
틱택토용으로 3x3 테이블은 한번에 만드는 코드는 table>(tr>td*3)*3 이다
그러면 아래와 같이 자동으로 아래 코드가 생성된다
<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>
위 코드만 치면 테이블이 모습을 나타내지 않기에 style을 넣어줘야한다.
<style>
td{
border: 1px solid black;
width: 80px;
height: 80px;
}
</style>

이것을 그대로 JS로 구현할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
var 바디 = document.body;
var 테이블 = document.createElement('table');
for (let i=1; i<4; i+=1){
var 행 = document.createElement('tr');
for(let j=1; j<4; j+=1){
var 열 = document.createElement('td');
행.appendChild(열);
}
테이블.appendChild(행);
}
바디.appendChild(테이블);

직장생활팁 : 실무에서는 무조건 html로 작성해야한다. 그게 더 효율적임. js로 나타낼 수 있다는 걸 알기만 하면 됨.




2. JS에서 HTML 태크 만들기

1
<div>태그만들기</div>

을 js에서 만들려면 아래와 같이 만들면 된다.

1
2
3
var div태그 = document.createElement('div'); //div태그를 만드는 것
div태그.textContent = '태그만들기'; // 만든 태그에 내용을 적는 것
document.body.append(div태그); // 만든 태그를 body에 표현하는 것. 이걸 꼭 해야함.

3가지가 세트라고 생각하면 됨. 3종세트!




3. 자식태그만들기

1
2
3
<div>태그만들기
<button>버튼</button>
</div>

을 js에서 만들려면 방법2가지가 있다.

1
2
3
4
5
6
7
8
9
방법 1 : append 쓰기

var div태그 = document.createElement('div');
div태그.textContent = '태그만들기';
document.body.append(div태그);

var 버튼태그 = document.createElement('button');
버튼태그.textContent = '등록';
div태그.append(버튼태그); //div태그(부모태그)안에 자식태그로 넣는 것.
1
2
3
4
5
6
7
8
9
방법 2 : appendChild 쓰기

var div태그 = document.createElement('div');
div태그.textContent = '태그만들기';
document.body.append(div태그);

var 버튼태그 = document.createElement('button');
버튼태그.textContent = '등록';
div태그.appendChild(버튼태그); //div태그(부모태그)안에 자식태그로 넣는 것.

둘 다 잘 작동한다

그렇다면 둘의 차이점은 무엇일까?




4. .append와 .appendChild의 차이점

1
2
3
<div>태그만들기
<button id='비교해보자'>등록</button>
</div>

기존 js

1
2
3
4
5
6
7
8
var div태그 = document.createElement('div'); 
div태그.textContent = '태그만들기';
document.body.append(div태그);

var 버튼태그 = document.createElement('button');
버튼태그.textContent = '등록';
버튼태그.id = '비교해보자'
div태그.append(버튼태그); //div태그(부모태그)안에 자식태그로 넣는 것.

위와 같이 이미 만들어져있는 HTML에서 ‘버튼’뒤에 string을 추가하고 싶다.

이때 2가지 비교해보자.

1
2
3
4
방법 1 : append 쓰기

기존 js의 아래부분에 추가한다
document.getElementById('비교해보자').append(" 이건 어팬드");

버튼안에 ‘버튼 이건 어팬드’라고 출력되며 잘 작동한다

두번째 appendChild쓰면 어떨까?

1
2
3
4
5
방법 2 : appendChild 쓰기

기존 js의 아래부분에 추가한다
document.getElementById('비교해보자').appendChild(" 이건 어팬드차일드");
//TypeError: Failed to execute 'appendChild' on 'Node': parameter 1 is not of type 'Node'.

타입에러가 난다.

왜일까?

appendChild는 element가 필요하기 때문.

따라서 아래와 같이 적어야한다.

1
2
3
4
5
6
7
8
방법 2-1 : appendChild 쓰기

기존 js의 아래부분에 추가한다
var 어팬드차일드 = document.createElement('text');
또는
var 어팬드차일드 = document.createElement('span');
어팬드차일드.textContent = ' 이건 어팬드차일드'
document.getElementById('비교해보자').appendChild(어팬드차일드);

버튼안에 ‘버튼 이건 어팬드차일드’라고 출력되며 잘 작동한다

만약 버튼 안의 text를 아예 바꾸고 싶다면 appendChild와 innerHTML를 세트로 사용하면 된다!

1
2
3
4
5
6
7
방법 2-2 : appendChild + innerHTML 세트로 쓰기

//이 방법은 기존js에서 수정이 필요하다
//div태그.append(버튼태그);에서 appendChild로 수정이 필요하다

div태그.appendChild(버튼태그);
document.getElementById('비교해보자').innerHTML =' 이건 어팬드차일드';

딱 2줄 바꿨다.

근데 이건 버튼태그안의 내용에 추가하는 게 아니라 내용 자체를 변경하는 것이다

따라서 버튼태그안의 text인 ‘등록’은 없어지고 ‘ 이건 어팬드차일드’만 남는다.



결론

  • 결론적으로 appendChild사용할 수 있는 모든 경우는 append 사용이 가능하지만, 그 반대는 아니다.
  • appendChild + innerHTML 세트로 사용하면 내용 변경에 유용하다
  • 참고링크 : https://rpubs.com/raulUbiqum/append




5. 2차원배열

3x3칸을 만들었다면 그 안에 O,X 배열을 넣어야 게임을 만들 수 있다.

그것을 2차원 배열이라고 하는데 아래처럼 보이게 만들고 싶다.

1
2
3
4
5
열들 = [
[첫칸, 두칸, 세칸]
[첫칸, 두칸, 세칸]
[첫칸, 두칸, 세칸]
]

어떻게 하면 될까?

2차원 배열을 만드는 방법 첫번째 스탭은

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//틱택토게임STEP1. JS로 3X3테이블만들기

var 바디 = document.body;
var 테이블 = document.createElement('table');
var 행들 = [];
var 열들 = [];
for (let i=1; i<4; i+=1){
var 행 = document.createElement('tr');
행들.push(행);
열들.push([]); //빈 배열 3개를 만듬 즉, 행 3개를 만듬
console.log(행들, 열들);
for(let j=1; j<4; j+=1){
var 열 = document.createElement('td');
행.appendChild(열);
}
테이블.appendChild(행);
}
바디.appendChild(테이블);

콘솔로그를 확인하면

빈 배열 3개가 생겼으므로 그 배열에 2차원 배열을 넣어야한다.

두번째 스탭은

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//틱택토게임STEP1. JS로 3X3테이블만들기

var 바디 = document.body;
var 테이블 = document.createElement('table');
var 열들 =[];
for (let i=1; i<4; i+=1){
var 행 = document.createElement('tr');
열들.push([]); //빈 배열 3개를 만듬 즉, 행 3개를 만듬
for(let j=1; j<4; j+=1){
var 열 = document.createElement('td');
열들[i-1].push(열); //왼쪽상단제일첫번째칸에 열을 넣는 것.
행.appendChild(열);
}
테이블.appendChild(행);
}
바디.appendChild(테이블);
console.log('행들' , 행들, '열들', 열들);

콘솔로그를 확인하면

짜잔- 2차원 배열 완성!




6. 2차원배열 클릭이벤트

이벤트리스너로 만든 2차원배열을 클릭할때마다 O,X를 나타나게끔 구현

3번의 들여쓰기가 있기에 코딩격언에 따라 ㅋㅋㅋ

변수에 function을 넣는다.

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
//틱택토게임STEP2. 2차원배열에 클릭하면 O,X 구현 

var 턴 = 'X';

var 비동기콜백 = function (이벤트){
console.log(이벤트.target); //열을 지목
console.log(이벤트.target.parentNode); //부모코드를 지목(=여기선 행)
console.log(이벤트.target.parentNode.parentNode); //조부모코드를 지목(=여기선 테이블)

var 몇번행 = 행들.indexOf(이벤트.target.parentNode); //인덱스오브로 몇줄인지 찾을 수 있음
console.log('몇줄', 몇번행);
var 몇번열 = 열들[몇번행].indexOf(이벤트.target);
console.log('몇칸', 몇번열);

// if(열들[몇번행][몇번열].value !== '') 여기서는 밸류가 아니라 텍스트콘텐트다
//input의 값이 value이고
//태그 안 글자는 textContent

if (열들[몇번행][몇번열].textContent !== ''){ //칸이 이미 채워져있는 경우
console.log('빈칸아닙니다')
}else{
console.log('빈칸입니다')
열들[몇번행][몇번열].textContent = 턴;
if (턴 === 'X'){
턴 = 'O';
}else {
턴 = 'X';
}
}
};
바디.append(결과);
  1. 이벤트.target = 열을 지목하는 것

  2. 이벤트.target.parentNode = 부모코드를 지목하는 것. 여기선 행으로 지정해놓았다

  3. 배열.indexOf(‘이거’) = 배열안에 ‘이거’가 몇번째에 있는지 순서를 알려준다.

참고 : https://www.w3schools.com/jsref/jsref_indexof_array.asp

  1. 2차원 배열을 클릭하면 X나O로 배열안의 내용을 바꿔주고 싶을 때는 .value가 아니라 .textContent이다.
1
2
열들[0][1].value = 'X' 여기서는 error 뜸 
열들[0][1].textContent = 'X' 여기서는 배열의 0번째행 1번째열이 'X'로 변경됨.

input의 값은 .value를 사용하고

태그 안 글자는 .textContent를 사용한다




7. 테이블의 3칸이 다 X거나 O로 채워졌는 지 구현

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
var 결과 = document.createElement('div');
//틱택토게임STEP3. 3칸이 다 X거나 O로 채워졌는 지 구현
var 다참 = false;
//가로줄검사
if(열들[몇번행][0].textContent === 턴 &&
열들[몇번행][1].textContent === 턴 &&
열들[몇번행][2].textContent === 턴){
다참 = true;
}
//세로줄검사
if(열들[0][몇번열].textContent === 턴 &&
열들[1][몇번열].textContent === 턴 &&
열들[2][몇번열].textContent === 턴){
다참 = true;
}
//대각선검사
if(몇번행 - 몇번열 === 0){
if(열들[0][0].textContent === 턴 &&
열들[1][1].textContent === 턴 &&
열들[2][2].textContent === 턴){
다참 = true;
}}
if(Math.abs(몇번행-몇번열)===2){
if(열들[0][2].textContent === 턴 &&
열들[1][1].textContent === 턴 &&
열들[2][0].textContent === 턴){
다참 = true;
}}

//다 찼으면
if (다참){
결과.textContent = 턴 +'님의 승리!';
console.log(턴 + '님의 승리!')
//승리한 뒤에는 초기화가 되어야한다. 아래는 초기화하는 코드.
턴 = 'X';
열들.forEach(function (){ //1차원으로 행을 먼저 선택한 후
행.forEach(function(){ //2차원으로 선택된 행에서의 열을 함께 선택함.
열.textContent = '';
});
});
}else{
if (턴 === 'X'){
턴 = 'O';
}else {
턴 = 'X';
}
}
}
};

2차원 배열이니까 반복문 2번씩 사용된다. 3차원배열이면 3번씩 사용됨.

중첩문을 줄이는게 코딩을 잘 하는 것.




8. 배열.forEach(function(){ })

1
2
3
4
5
6
7
8
9
[1,2,3,4,5].forEach(function(엘리먼트){  //배열안의 것들을 요소(element)라고 부름
console.log(엘리먼트);
});
//output =>
1
2
3
4
5

참고 : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach