-
JavaScript 입문: 틱택토 게임 - 컴퓨터와 게임 (무작위 순서 이용)컴퓨터 알아가기/JavaScript 2022. 8. 28. 19:30728x90반응형
이 글은 제로초 TV의 자바스크립트 강좌를 기본으로 하고 있습니다.
이차원배열을 일차원배열로 바꿔 코딩을 단순화 했으니 형식적으로라도 사람과 컴퓨터가 게임을 하는듯한 프로그램을 공부해 보고자 합니다. 즉 turn이 사람과 컴퓨터 순으로 바꾸면 될 듯 합니다.
컴퓨터가 turn을 하기 위해서는 순서도상 다음 부분에서 추가를 해주어여 될 듯 합니다.
여기서 확인할 수 있는 것은 지금까지 만든 코딩은 사람이 먼저 'O'를 입력하면 또 다른 사람이 'X'를 입력하는 방식이었습니다. 그 가운데 승부여부와 무승부에 대한 원리를 알아보았구요. 이제는 컴퓨터가 'X'를 입력할 수 있도록 턴을 변경해 주면서 승부판단을 해야 합니다.
1. 컴퓨터 턴 만들기
지난번 만든 것과 같은 컴퓨터의 턴을 이번에도 만들어 보겠습니다. CSS 모양은 지난번 것이 훨씬 좋긴 한데 두가지를 다 공부하는 이유는 결과는 같지만 서로 다른 코딩방식이라는 점 때문입니다. 참고로 다른 방식은 아래 링크를 같이 걸어 놓겠습니다.
2022.08.25 - [컴퓨터 알아가기/JavaScript] - JavaScript 입문 : 컴퓨터와 함께하는 틱택토 게임 (TicTacToe)
우선 컴퓨터 순서를 만들기 위해서 사람인 유저가 'O'를 입력하면 turn은 'X'여야 하고 이럴경우 나머지 빈칸을 찾아서 'X'를 입력해 줘야 합니다. 코딩은 사람이 할 경우와 같습니다.
상기 코드의 핵심은 빈칸을 filter( ) 메소드로 찾는 것과 찾은 빈칸의 배열의 인덱스를 구해 'X'를 표시해 주는 겁니다.
2. 중복 제거
가만히 보면 사람이 하는 부분과 컴퓨터가 하는 부분에서 중복이 되는 부분이 있습니다. 승부 판단과 무승부 판단 그리고 턴을 넘기는 과정입니다.
이 부분을 통합하도록 하겠습니다.
혼동 될 수 있는 부분이 사람이 하는 경우 decisionWinner(e.target)이었고 컴퓨터가 하는 부분이 decisionWinner(randomCell)로 표시를 하였습니다. 결국 괄호안에 들어가는 함수실행 매개체는 전부 cell입니다. cell은 곧 <td> 이고 이는 결국 target입니다.
따라서 다음과 같이 중복을 제거하고 하나로 나타내면 됩니다.
상기와 같이 코드를 정리하면 checkWinnerDraw라는 함수로 통일하며 최종적으로 각각 승부판단이 이루어지는 곳에 함수를 선언하면 됩니다.
3. 컴퓨터 텀 주기
현재까지는 'O'를 입력하면 바로 컴퓨터가 빈칸에 'X'를 나타냅니다. 약간 시간을 주는게 필요할 듯 합니다. 예전에 사용하였던 setTimeout( ) 메소드를 이용하여 시간을 1초나 2초를 반영하도록 하겠습니다.
아울러 setTimeout( ) 메소드를 사용하면 항상 기억해 둘게 비동기 함수이기 때문에 시간차 내에서도 이벤트(믈릭)가 적용이 됩니다. 따라서 항상 flag 변수로 true와 false를 이벤트가 발생하는 길목에 배치해 두는게 포인트입니다.
flag 변수를 선언하고 컴퓨터 턴이 되는 경우는 클릭이 되지 않게 하고 컴퓨터 턴이 끝나면 턴이 될 수 있게 만드는 겁니다.
다음 코드를 보면 알 수 있습니다.
전체코드는 다음과 같습니다.
// 변수 const { body } = document; // 구조할당, document는 객체로 향후 생략 가능 const $result = document.createElement('div'); // reult표시를 위해 <div>태그 만듦 let turn = 'O'; // 순서 변수 const rows = []; // decisionWinner( ) 함수식 // ① 반복문을 통하여 각 칸에 있는 위치 지정 const decisionWinner = (target) => { // target은 곧 cell이고 cellIndex const rowIndex = target.parentNode.rowIndex; // row는 cell의 부모노드, forEach가 필요없음 const cellIndex = target.cellIndex; // cellIndex를 전부 가져오는 것, forEach가 필요없음 // 승부 판단전 칸이 비어있는지 여부, 승자가 있는지 여부 let existWinner = false; // 가로줄 검사 (각 칸의 세로가 맞아야) // [ [00], [01], [02] // [10], [11], [12] // [20], [21], [22] // ] if (rows[rowIndex][0].textContent === turn && rows[rowIndex][1].textContent === turn && rows[rowIndex][2].textContent === turn) { existWinner = true; } // 세로줄 검사 (각 칸 가로가 맞아야) if (rows[0][cellIndex].textContent === turn && rows[1][cellIndex].textContent === turn && rows[2][cellIndex].textContent === turn) { existWinner = true; } // 대각선 검사 if (rows[0][0].textContent === turn && rows[1][1].textContent === turn && rows[2][2].textContent === turn) { existWinner = true; } if (rows[0][2].textContent === turn && rows[1][1].textContent === turn && rows[2][0].textContent === turn) { existWinner =true; } return existWinner; } // 중복제거후 하나로 통일 (승부판단, 무승부, 턴) const checkWinnerDraw = (target) => { const whoWinner = decisionWinner(target); // 승자가 있으면 if (whoWinner) { $result.textContent = `${turn} 승리`; $table.removeEventListener('click', turnback); return; } // 승자가 없으면 (무승부) const number = rows.flat().every((cell) => cell.textContent); if (number) { $result.textContent = `무승부`; return; } turn = turn === 'O'? 'X' : 'O'; }; // callback 함수 밖으로 빼기 let clickable = true; // 클릭하는것을 true로 const turnback = (e) => { // 9개의 td를 클릭하기 위하여 if (!clickable) return; // 클릭못하는 경우 return console.log('clicked'); if (e.target.textContent !== '') { // 빈칸이 아니면 console.log('빈칸이 아닙니다'); return; // else 없애기 위해 (if의 if 중첩은 안좋음) } // 빈칸이면 console.log('빈칸입니다.'); e.target.textContent = turn; // 활성화 checkWinnerDraw(e.target); // 컴퓨터 순서에 대한 코딩추가 if (turn === 'X') { clickable = false; // 컴퓨터 순서일때 클릭 못하게 // 컴퓨터 시간 추가 setTimeout(() => { const emptyCells = rows.flat().filter((f) => !f.textContent); // 비어있는 곳 filtering // 빈 셀을 다 찾았으면 랜덤하게 하나를 뽑아야 함 const randomCell = emptyCells[Math.floor(Math.random() * emptyCells.length)]; randomCell.textContent = 'X'; // 'X'로 채운다 checkWinnerDraw(e.target); clickable = true; // 컴퓨터 턴이 끝나면 클릭 가능 }, 1000) // 1초후 반응 } }; // 3 by 3 테이블 만들기 const $table = document.createElement('table'); // append를 위한 table 활성화 (1번) for (let i = 0; i < 3; i++) { // 테이블안에 3개의 tr 만들기 (2번) const $tr = document.createElement('tr'); const cells = []; for (let j = 0; j < 3; j++) { // tr안에 3개의 td 만들기 (3번) const $td= document.createElement('td'); cells.push($td); // cell에 td를 push $tr.append($td); // (3번) } rows.push(cells); $table.append($tr); // (2번) } $table.addEventListener('click', turnback); body.append($table); // 만든 테이블 전체 프레임 append (1번), document 생략 body.append($result); // result 결과표시, document 생략
반응형'컴퓨터 알아가기 > JavaScript' 카테고리의 다른 글
JavaScript 입문 : JSON.stringify( ) 메소드 이해 (0) 2022.08.30 JavaScript 입문 : JSON이란 도대체 무엇인가? (기본 개념) (0) 2022.08.29 JavaScript 입문: 틱택토 게임 - 코딩 단순화 (이차원배열을 일차원배열로) (0) 2022.08.27 JavaScript 입문 : 컴퓨터와 함께하는 틱택토 게임 (TicTacToe) (0) 2022.08.25 VS code에서 JavaScript 실행하기 : Node.js 및 Code Runner (3) 2022.08.24