코딩/1-JavaScript

03_순발력게임1단계 ~ 03_순발력게임3단계

tree0505 2025. 6. 5. 10:41
반응형
  • 03_순발력게임1단계
  • _speedgame1.html
  • 1 to 50 
    • 배열이 2개이다.
    • 첫번째를 다 벗겨내면. 2번째할때는 빈칸이 된다. 
  • cursor: pointer;는 셀 위에 마우스를 올리면 손 모양이 나타나게 해서 **"클릭할 수 있다"**는 시각적 힌트를 줍니다.
  • onload="init()"는 페이지가 로드되자마자 init() 함수 실행하라는 의미입니다.
  • 매우 중요! → JS로 화면을 그리려면 언제 실행할지 타이밍을 잡는 게 중요해요.
  • 화면에 들어갈 3개의 영역을 구분해 놓았어요.
    • #header: 제목
    • #center: 테이블이 들어갈 자리
    • #footer: 나중에 점수나 타이머 같은 부가 요소 들어갈 수도 있어요.
  • 첫번째 반복문 
    • 첫 번째 반복문은 "숫자 데이터를 세팅(초기화)"하기 위한 것
    • 📦 두 반복문의 역할 비교:
    • 반복문 위치목적무슨 일 하는지
      첫 번째 반복문 (num, frontList, backList) ❗ 데이터 준비 125, 2650 숫자들을 2차원 배열에 저장 (게임판 데이터 만들기)
      두 번째 반복문 (DOM 조작) ❗ 화면에 보여주기 + 이벤트 연결 <table> 태그를 만들고, 셀(<td>)을 추가하고, 숫자 넣고, 클릭 이벤트도 연결
    • ✨ 이 코드는 화면에는 아무것도 출력하지 않지만,
    • 👉 **나중에 사용할 게임판 데이터를 2차원 배열 형태로 준비해주는 "세팅 작업"**입니다.
  • 2번째 반복문 
    • 테이블을 화면에 보여주고, 각 칸에 숫자를 넣고,
      클릭할 수 있도록 이벤트까지 연결하는 핵심 코드
<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>

    <style>
        #header { text-align: center; }
        table {
            border-collapse: collapse;
            border: 1px solid black;
            margin: auto;
        }
        td {
            width: 50px;
            height: 50px;
            border: 1px solid black;
            text-align: center;

            cursor: pointer;
        }
    </style>

</head>
<body onload="init()">

    <div id="header">
        <h3>Speed Game</h3>
    </div>

    <div id="center"></div>
   
    <div id="footer"></div>
   
    <script>
        let size = 5;
       변수 선언 
$table은 새로 <table>을 만들어서 화면에 붙일 준비를 합니다.
👉 DOM 조작의 핵심: 요소를 만들고, 붙이고, 속성 설정하고
        let frontList = []; // 1 ~ 25 수를 저장하는 2차배열
        let backList = [];  // 26 ~ 50 수를 저장하는 2차배열
        let $center = document.querySelector("#center");
        let $table = document.createElement("table");
        let $tdList = []; //집어 넣을것
---------------------------------------------------------------------------------
        function init() {
초기 세팅 
            let num = 1;
            for(let i=0; i<size; i++) {
                let frontTemp = [];
                let backTemp = [];
                for(let j=0; j<size; j++) {
                    frontTemp.push(num);
                    backTemp.push(num + 25);

                    num += 1;
첫번째 판을 다 지우면 2번째 판도 만들어야 해서. 판이 2개라서. 배열을 2개를 저장시키는것 
테이블에 숫자가 두겹으로 숨겨져 있는 구조이다. 
지금은 첫 번째 판만 보이게 설정해 놓은것 
backList의 숫자들 → 화면에는 아직 안 나옴, 하지만 데이터로는 저장되어 있음
                }

                frontList.push(frontTemp);
                backList.push(backTemp);
            }

            console.log("frontList = " + frontList);
            console.log("backList = " + backList);
--------------------------------------------------------------------------
            for(let i=0; i<size; i++) {
숫자들을 화면에 보여주고. 클릭이벤트 넣어주기 
                let $tr = document.createElement("tr"); 
  • <tr>(테이블 한 행)을 새로 만드는 코드
  • 지금부터 여기에 <td>(칸)를 하나씩 넣을 거예요
               
                let $tempTdList = [];
  • 한 줄 안의 <td>들(5개)을 배열에 따로 모아두기 위한 변수
  • 나중에 게임 상태를 관리하거나 바꾸기 쉽게 하기 위해 2차원 배열 형태로 저장
                for(let j=0; j<size; j++) {
                    let $td = document.createElement("td");
  • <td> 하나 생성 (테이블 셀)
  • 이 안에 숫자도 넣고, 클릭도 할 수 있도록 만들 거예요
 
                    $td.addEventListener("click", clickEvent);
  • 이 칸을 클릭했을 때 실행할 함수를 연결
  • 여기선 clickEvent()라는 함수를 연결했어요 (아직 비어 있음)

👉 이 부분이 없으면 셀을 클릭해도 아무 반응 없음

                    $td.innerText = frontList[i][j]; //프론트에만 넣어줌 // 지금 화면에 첫번째 판만 보여준 것 
  • 해당 위치의 숫자(1~25)를 텍스트로 넣어줌
  • frontList는 미리 준비해둔 2차원 배열이고, 그걸 꺼내서 화면에 보여주는 거예요

예시: frontList[0][0] → 1

                   
                    $tr.append($td);  만든 <td> 셀을 현재 줄(<tr>)에 붙임
                    $tempTdList.push($td);
  • 화면에 표시된 <td> 요소를 배열에 저장
  • 이유: 나중에 이걸 바꾸거나 업데이트할 수 있도록 하기 위해
                }
               
                $tdList.push($tempTdList);
                $table.append($tr);
  • td 셀 배열을 tdList에 저장 → 전체 테이블을 배열로 관리할 수 있게 됨 (2차원 배열 형태)
  • 줄 <tr>을 완성된 테이블에 붙임
            }
            $center.append($table);
  • 완성된 테이블을 실제 웹페이지의 #center에 붙임
  • 이제 눈에 보이게 됨
        }

        function clickEvent() {
        }

    </script>

</body>
</html>

콘솔


  • 03_순발력게임2단계
  • _speedgame2.html
  • 다음숫자로 덮어씌워짐 
  • 2번째는 0으로 만들기
    <!DOCTYPE html>
    <html lang="ko">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>

        <style>
            #timer { text-align: center; }
            #header { text-align: center; }
            table {
                border-collapse: collapse;
                border: 1px solid black;
                margin: auto;
            }
            td {
                width: 50px;
                height: 50px;
                border: 1px solid black;
                text-align: center;

                cursor: pointer;
            }
        </style>

    </head>
    <body onload="init()">

        <div id="timer">0</div>

        <div id="header">
            <h3>Speed Game</h3>
            <button onclick="hintClick()">힌트</button>
            <span id="nextNum">1</span>
        </div>

        <div id="center"></div>
       
        <div id="footer"></div>
       
        <script>
            let gameNum = 1;        // 추가된 변수
            let time = 0;          

            let size = 5;
            let frontList = [];
            let backList = [];
            let $center = document.querySelector("#center");
            let $table = document.createElement("table");
            let $tdList = [];

            function init() {
                let num = 1;
                for(let i=0; i<size; i++) {
                    let frontTemp = [];
                    let backTemp = [];
                    for(let j=0; j<size; j++) {
                        frontTemp.push(num);
                        backTemp.push(num + 25);

                        num += 1;
                    }

                    frontList.push(frontTemp);
                    backList.push(backTemp);
                }

                // 셔플(shuffle)
                /*
                for(let i=0; i<100; i++) {
                    let y = Math.floor(Math.random() * size);
                    let x = Math.floor(Math.random() * size);

                    let temp = frontList[0][0];
                    frontList[0][0] = frontList[y][x];
                    frontList[y][x] = temp;

                    y = Math.floor(Math.random() * size);
                    x = Math.floor(Math.random() * size);

                    temp = backList[0][0];
                    backList[0][0] = backList[y][x];
                    backList[y][x] = temp;
                }
                */

                console.log("frontList = " + frontList);
                console.log("backList = " + backList);

                for(let i=0; i<size; i++) {
                    let $tr = document.createElement("tr");
                   
                    let $tempTdList = [];
                    for(let j=0; j<size; j++) {
                        let $td = document.createElement("td");
                        $td.addEventListener("click", clickEvent);
                        $td.innerText = frontList[i][j];
                       
                        $tr.append($td);
                        $tempTdList.push($td);
                    }
                   
                    $tdList.push($tempTdList);
                    $table.append($tr);
                }
                $center.append($table);
            }

            function setTimer() {
                time += 1;
                document.querySelector("#timer").innerText = time;
            }
    //----------------------------------------------------------------
    //누르면 현재 위치를 찾기 // 내가 누른 위치 찾기
            function clickEvent() {
                let y = 0;
                let x = 0;
                for(let i=0; i<size; i++) {
                    for(let j=0; j<size; j++) {
                        if(this == $tdList[i][j]) {
                            y = i;
                            x = j;
                            break;
                        }
                    }
                }
                if(this.innerText == gameNum) {
                    if(1 <= gameNum && gameNum <= 25) {
                        if(gameNum == 1) {
                            setInterval(setTimer, 1000);
                            //숫자 1이면 타이머를 동작시킴
                        }
                        this.innerText = backList[y][x];
                        //백에 있는것을 집어 넣는다.
                    } else {
                        this.innerText = 0;
                        //26~50이면 0을 집어 넣는다.
                    }
                    this.style.backgroundColor = "";
                    //힌트를 지우는 역할
                    gameNum += 1; //숫자 2로 만들어 주기

                    document.querySelector("#nextNum").innerText = gameNum;
                    //힌트 빨간색을 지우기 위해서
                }
            }
    //힌트 누르면 빨간색 넣어주기
            function hintClick() {
                let y = 0;
                let x = 0;
                for(let i=0; i<size; i++) {
                    for(let j=0; j<size; j++) {
                        if($tdList[i][j].innerText == gameNum) {
                            y = i;
                            x = j;
                            break;
                        }
                    }
                }

                $tdList[y][x].style.backgroundColor = "red";
            }
        </script>

    </body>
    </html>

  • 03_순발력게임3단계
  • _speedgame3.html
  • 게임이 끝나면 다시 할 수 있게. 깔끔히
    <!DOCTYPE html>
    <html lang="ko">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>

        <style>
            #timer { text-align: center; }
            #header { text-align: center; }
            #footer { text-align: center; }
            table {
                border-collapse: collapse;
                border: 1px solid black;
                margin: auto;
            }
            td {
                width: 50px;
                height: 50px;
                border: 3px solid white;
                text-align: center;
                color: brown;
                font-size: 20px;
                font-weight: bold;

                cursor: pointer;
            }
        </style>

    </head>
    <body onload="init()">

        <div id="timer">0</div>

        <div id="header">
            <h3>Speed Game</h3>
            <button onclick="hintClick()">힌트</button>
            <span id="nextNum">1</span>
        </div>

        <div id="center"></div>
       
        <div id="footer">
            <button onclick="replayClick()">Replay</button>
        </div>
       
        <script>
            let gameNum = 1;        // 추가된 변수
            let time = 0;    
            let timeId = null;      

            let size = 3;
            let frontList = [];
            let backList = [];
            let $center = document.querySelector("#center");
            let $table = document.createElement("table");
            let $tdList = [];

            function init() {
                let num = 1;
                for(let i=0; i<size; i++) {
                    let frontTemp = [];
                    let backTemp = [];
                    for(let j=0; j<size; j++) {
                        frontTemp.push(num);
                        backTemp.push(num + size*size);

                        num += 1;
                    }

                    frontList.push(frontTemp);
                    backList.push(backTemp);
                }

                //원래는 섞어야 한다.
                // 셔플(shuffle)
                /*
                for(let i=0; i<100; i++) {
                    let y = Math.floor(Math.random() * size);
                    let x = Math.floor(Math.random() * size);

                    let temp = frontList[0][0];
                    frontList[0][0] = frontList[y][x];
                    frontList[y][x] = temp;

                    y = Math.floor(Math.random() * size);
                    x = Math.floor(Math.random() * size);

                    temp = backList[0][0];
                    backList[0][0] = backList[y][x];
                    backList[y][x] = temp;
                }
                */

                console.log("frontList = " + frontList);
                console.log("backList = " + backList);

                for(let i=0; i<size; i++) {
                    let $tr = document.createElement("tr");
                   
                    let $tempTdList = [];
                    for(let j=0; j<size; j++) {
                        let $td = document.createElement("td");
                        $td.addEventListener("click", clickEvent);
                        $td.innerText = frontList[i][j];
                        $td.style.backgroundColor = "coral";
                       
                        $tr.append($td);
                        $tempTdList.push($td);
                    }
                   
                    $tdList.push($tempTdList);
                    $table.append($tr);
                }
                $center.append($table);
            }

            function setTimer() {
                time += 1;
                document.querySelector("#timer").innerText = time;
            }

            function clickEvent() {
                let y = 0;
                let x = 0;
                for(let i=0; i<size; i++) {
                    for(let j=0; j<size; j++) {
                        if(this == $tdList[i][j]) {
                            y = i;
                            x = j;
                            break;
                        }
                    }
                }
                if(this.innerText == gameNum) {
                    if(1 <= gameNum && gameNum <= size*size) {
                        if(gameNum == 1) {
                            timeId = setInterval(setTimer, 1000);
                        }
                        this.innerText = backList[y][x];
                        this.style.backgroundColor = "antiquewhite";
                    } else {
                        this.innerText = "";
                        this.style.backgroundColor = "";

                        this.style.cursor = "default";
                    }
                    gameNum += 1;

                    document.querySelector("#nextNum").innerText = gameNum;
                }

                gameOver();
            }

            function hintClick() {
                let y = 0;
                let x = 0;
                for(let i=0; i<size; i++) {
                    for(let j=0; j<size; j++) {
                        if($tdList[i][j].innerText == gameNum) {
                            y = i;
                            x = j;
                            break;
                        }
                    }
                }

                $tdList[y][x].style.backgroundColor = "red";
            }
       
            function clearTable() {
                $center.removeChild($table );
            }
            //-------------------------------------------------
            function replayClick() { //리플라이 버튼을 누르면
                clearInterval(timeId); //타이머 정지
                clearTable(); // 테이블 지우기

                // 변수 초기화
                gameNum = 1;      
                time = 0;    
                timeId = null;
                frontList = [];
                backList = [];
                $table = document.createElement("table");;
                $tdList = [];
                document.querySelector("#timer").innerText = time;
                document.querySelector("#nextNum").innerText = gameNum;

                init(); //다시 시작
            }
            //---------------------------------------------------------
            //게임오버를 판단하는것 .
            function gameOver() {
                if(gameNum > size*size*2) { //마지막 숫자는 게임오버
                    clearInterval(timeId); //멈춤

                    // 게임 종료 화면
                    alert("게임을 종료합니다!");
                }
            }

        </script>

    </body>
    </html>

  • _speedgame2 copy.html
<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>

    <style>
        #timer { text-align: center; }
        #header { text-align: center; }
        table {
            border-collapse: collapse;
            border: 1px solid black;
            margin: auto;
        }
        td {
            width: 50px;
            height: 50px;
            border: 1px solid black;
            text-align: center;

            cursor: pointer;
        }
    </style>

</head>
<body onload="init()">

    <div id="timer">0</div>

    <div id="header">
        <h3>Speed Game</h3>
        <button onclick="hintClick()">힌트</button>
        <span id="nextNum">1</span>
    </div>

    <div id="center"></div>
   
    <div id="footer"></div>
   
    <script>
        let gameNum = 1;        // 추가된 변수
        게임에서 지금 몇 번 숫자를 눌러야 하는지를 알려주는 변수예요.
        힌트. 다음에 눌러줄 번호. 
        화면에서도 <span id="nextNum">1</span>으로 현재 목표 숫자를 표시하죠.
        let time = 0;    
        타이머 숫자를 나타냄.
        1초마다 1씩 증가하는 구조 (setInterval로 호출됨)

        let size = 5;
        let frontList = [];    실제로 **처음 화면에 보이는 숫자들(1~25)**을 저장할 2차원 배열
        let backList = [];    클릭하고 나면 보이게 될 **두 번째 숫자들(26~50)**을 저장할 2차원 배열
        즉, 게임판에 두 겹의 숫자가 있는 구조입니다!
        let $center = document.querySelector("#center");
        let $table = document.createElement("table");   여기서 테이블을 만듬 
        let $tdList = [];
 
        보통 center은 body에서 만들고. 테이블과 tr과 td는 자바스크립트( script)에서 만든다. 
 
        $를 붙인것 => 이 변수는 HTML 요소야 => 화면에 출력하는것 
------------------------------------------------------------------------------------
        function init() {    게임 시작 시 호출되는 함수    
          숫자 데이터 준비 (frontList, backList)
            let num = 1;
            for(let i=0; i<size; i++) {
                let frontTemp = [];
                let backTemp = [];
                행(row) 기준으로 반복문 시작    .  각 줄마다 frontTemp, backTemp 라는 임시 배열을 만들어요
                for(let j=0; j<size; j++) {
                    frontTemp.push(num);
                    backTemp.push(num + 25);

                    num += 1;
                    열(column) 기준 반복
                }

                frontList.push(frontTemp);
                backList.push(backTemp);
                위에서 만든 한 줄씩의 배열을 전체 배열에 넣음  .  이렇게 해서 5×5짜리 2차원 배열이 완성됩니다.  
            }
 

왜 이렇게 했을까?

  • 게임에서 셀을 누르면 숫자가 바뀌어야 하니까
    👉 숫자 데이터(1~50)를 미리 배열에 다 준비해둔 것
  • 테이블은 나중에 따로 만들어서 화면에만 보여줌
  • 실제 DOM 조작은 init()의 아래쪽에서 실행됨

"실제 DOM 조작은 init()의 아래쪽에서 실행됨"이라는 말은,

init() 함수 안에서 페이지에 보여지는 실제 HTML 요소들(<table>, <tr>, <td>)을 생성하고, 그걸 문서의 원하는 위치(예: #center div)에 추가하는 작업이 init() 함수의 후반부에 일어난다는 뜻이에요.

쉽게 말하면:

  • init() 함수는 크게 두 가지 일을 해요:
    1. 데이터 세팅 (숫자 배열 frontList, backList 만들기)
    2. 화면에 보여줄 HTML 요소 생성과 추가 (DOM 조작)
  • 여기서 “DOM 조작”이란, 자바스크립트로 HTML 태그를 만들고,
    그 태그를 화면에 있는 특정 요소 안에 넣는 작업을 말해요.
  • 이 작업은 보통 init() 함수 코드 중간~아래쪽에 위치해요.

 

 

  • 자바스크립트는 데이터만 만들고, 실제 화면에 요소를 추가하는 건 DOM 조작이기 때문
  • 데이터만 만들면 화면에는 아무것도 안 보임
  • 화면에 뭔가 보여주려면 DOM 조작이 필수

init() 함수에서 데이터 준비가 끝난 뒤,
HTML 요소를 만들고 화면에 넣는 작업(=DOM 조작)이 함수 아래쪽에서 이뤄진다.
그래서 실제 화면에 테이블과 숫자가 나타나는 부분이 init() 함수 내 후반부라는 의미입니다.

 

-----------------------------------------------------------------------------
            // 셔플(shuffle)
            /*
            for(let i=0; i<100; i++) }     // 100번 섞는다. 
                let y = Math.floor(Math.random() * size);
                let x = Math.floor(Math.random() * size);

                let temp = frontList[0][0];
                frontList[0][0] = frontList[y][x];
                frontList[y][x] = temp;

                y = Math.floor(Math.random() * size);
                x = Math.floor(Math.random() * size);

                temp = backList[0][0];
                backList[0][0] = backList[y][x];
                backList[y][x] = temp;
            }
            */

            console.log("frontList = " + frontList);
            console.log("backList = " + backList);
--------------------------------------------------------------------------
화면에 보여주는 용도. 아직 클릭 이벤트는 연결만 했지. 실행은 안됨 
            테이블, tr, td 요소 생성 및 이벤트 연결 
           
               for(let i=0; i<size; i++) {
                let $tr = document.createElement("tr");
                size가 5라면, 5번 반복해서 테이블의 행을 5개 만들어요.
                document.createElement("tr")는 HTML에서 <tr></tr> 태그를 새로 생성하는 메서드입니다.
               
                let $tempTdList = [];   
                각 행에 포함될 <td> 태그(셀)들을 담을 임시 배열
                이 배열은 현재 행에 생성되는 셀들을 저장해요
                나중에 클릭 이벤트 등을 위해 저장해 두는 용도입니다.
 
                for(let j=0; j<size; j++) {
                    let $td = document.createElement("td");
                    $td.addEventListener("click", clickEvent);    셀에 클릭 이벤트 함수 연결
                    $td.innerText = frontList[i][j];          셀 안에 숫자 텍스트 넣기
                   
                    $tr.append($td);      생성한 셀(<td>)을 현재 행(<tr>)에 추가
                    $tempTdList.push($td);    현재 행의 셀 배열에도 저장
                }
               
                $tdList.push($tempTdList);      완성된 한 행의 셀 배열을 전체 셀 배열에 추가
                $table.append($tr);      완성된 행(<tr>)을 테이블(<table>)에 붙임
            }
            $center.append($table);
            3. 완성된 테이블을 center 영역에 넣음 — 이게 바로 실제 DOM 조작
            완성된 테이블을 화면의 #center 요소 안에 추가
            이렇게 해야 실제로 화면에 테이블이 보입니다!
        }
        타이머 증가 함수 (setTimer)
        function setTimer() {
            time += 1;    1초가 지날 때마다 time 변수 1 증가
            document.querySelector("#timer").innerText = time;    증가한 time 값을 화면의 #timer 요소에 표시
        }
//----------------------------------------------------------------
//누르면 현재 위치를 찾기 // 내가 누른 위치 찾기
        function clickEvent() { //누르면
            let y = 0;
            let x = 0;
            for(let i=0; i<size; i++) {
                for(let j=0; j<size; j++) {
                    if(this == $tdList[i][j]) {
                        //this 내가 누른것
                        //$tdList[i][j] => td를 담아놓은 데이터
                        //누가 눌렸는지 찾는것
                        //내가 누른거랑. 전체배열에 있는 데이터가 같으면
                        //위치를 찾는다!!!!1
                        y = i;
                        x = j;
                        break;
                    }
                }
            }
this는 지금 클릭한 td 요소 자체를 뜻해. (이 함수가 td에서 호출되었으니까)
 
            if(this.innerText == gameNum) {
                //this.innerText => 내가 누른 숫자가.
                //gameNum => 내가 맞춰야 되는 숫자.
                if(1 <= gameNum && gameNum <= 25) {
                    if(gameNum == 1) { //타이머 시작
                        setInterval(setTimer, 1000);
                        //숫자 1이면 타이머를 동작시킴
                    }
                    this.innerText = backList[y][x];
                    //백에 있는것을 집어 넣는다.
                } else {
                    this.innerText = 0;
                    //26~50이면 0을 집어 넣는다.
                }
                this.style.backgroundColor = "";   //색이 있으면 지우고. //힌트
                //힌트를 지우는 역할
                gameNum += 1; //숫자 2로 만들어 주기

                document.querySelector("#nextNum").innerText = gameNum;
                //힌트 빨간색을 지우기 위해서
               /다음 맞춰야 되는 숫자.
                //힌트 빨간색을 지우기 위해서
            }
        }
------------------------------------------------------------------------------------------------------
//힌트 누르면 빨간색 넣어주기
        function hintClick() {
            let y = 0;
            let x = 0;
           
 //위치 다시 찾아서. 빨간색으로 바꾸기.
            for(let i=0; i<size; i++) {
                for(let j=0; j<size; j++) {
                    if($tdList[i][j].innerText == gameNum) {
                        y = i;
                        x = j;
                        break;
                    }
                }
            }

            $tdList[y][x].style.backgroundColor = "red";
        }
    </script>

</body>
</html>

  • 03_순발력게임3단계
  • _speedgame3 copy 2.html
<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>

    <style>
        #timer { text-align: center; }
        #header { text-align: center; }
        #footer { text-align: center; }
        table {
            border-collapse: collapse;
            border: 1px solid black;
            margin: auto;
        }
        td {
            width: 50px;
            height: 50px;
            border: 3px solid white;
            text-align: center;
            color: brown;
            font-size: 20px;
            font-weight: bold;

            cursor: pointer;
        }
    </style>

</head>
<body onload="init()">

    <div id="timer">0</div>

    <div id="header">
        <h3>Speed Game</h3>
        <button onclick="hintClick()">힌트</button>
        <span id="nextNum">1</span>
    </div>

    <div id="center"></div>
   
    <div id="footer">
        <button onclick="replayClick()">Replay</button>
    </div>
   
    <script>
        let gameNum = 1;        // 추가된 변수
        //게임에서 현재 눌러야 하는 숫자를 저장하는 변수야
        //예를 들어, 플레이어가 1부터 차례로 눌러야 하면, 처음엔 1, 그 다음엔 2, 3... 이런 식으로 증가함.
        let time = 0;    
        //**게임 시작 후 경과한 시간(초)**를 저장하는 변수야.
        //타이머가 1초씩 증가할 때마다 time도 1씩 올라가.
        let timeId = null;      
        //setInterval 함수가 반환하는 타이머 ID를 저장하는 변수야.
        // 이 값을 이용해 clearInterval(timeId)로 타이머를 멈출 수 있어.
        // 초기값은 아직 타이머가 안 시작됐으니까 null로 둠.

        let size = 3;
        let frontList = [];
        let backList = [];
        let $center = document.querySelector("#center");
        //HTML 문서에서 id가 "center"인 요소를 찾아서 저장한 변수야.
        //이 요소 안에 동적으로 테이블(<table>)을 만들어 넣는 데 사용함.
        let $table = document.createElement("table");
        //새로 만들 HTML 테이블 요소(<table>)를 생성해서 저장한 변수.
        let $tdList = [];
        //테이블의 각 칸(td 요소)을 2차원 배열로 저장하는 변수야.
        //예를 들어 $tdList[0][0]은 첫 번째 행 첫 번째 열의 <td> 요소.
        // 클릭했을 때 어떤 칸이 눌렸는지 쉽게 찾기 위해서임.
        //2차배열 $tdList는 배열이고,
        // 그 안에 또 다른 배열들이 들어있어 ($tempTdList).
        // 각 $tempTdList 배열에는 <td> 요소들이 쭉 들어가 있지.
        // 즉, $tdList[i][j] 형태로 행(i)과 열(j) 위치의 <td> 요소에 접근할 수 있어.
        // 그래서 2차원 배열이라고 해!
//---------------------------------------------------------------------------------------------
        function init() {
            let num = 1;
            for(let i=0; i<size; i++) {
                   // num은 여기서 초기화 안됨. 계속 유지됨.
                let frontTemp = [];
                let backTemp = [];
                for(let j=0; j<size; j++) {
                    frontTemp.push(num);
                    backTemp.push(num + size*size);

                    num += 1;
                }

                frontList.push(frontTemp);
                backList.push(backTemp);
            }
            /*
            frontList = [
                [1, 2, 3],    // 1행
                [4, 5, 6],    // 2행 - 이전 숫자에서 이어서 증가
                [7, 8, 9]     // 3행
]
                */
//----------------------------------------------------------------------------
            //원래는 섞어야 한다.
            // 셔플(shuffle)
           
            for(let i=0; i<100; i++) {
                let y = Math.floor(Math.random() * size);
                let x = Math.floor(Math.random() * size);

                let temp = frontList[0][0]; //2차배열이다.
             
                frontList[0][0] = frontList[y][x];
                frontList[y][x] = temp; //??

                y = Math.floor(Math.random() * size); //?? 왜 또 랜덤?
                x = Math.floor(Math.random() * size);
                //frontList와 backList를 각각 독립적으로 섞기 위해서야.

                temp = backList[0][0];
                backList[0][0] = backList[y][x];
                backList[y][x] = temp;
            }
           

            console.log("frontList = " + frontList);
            console.log("backList = " + backList);

//-------------------------------------------------------------------------------
            for(let i=0; i<size; i++) {
                let $tr = document.createElement("tr");
               
                let $tempTdList = [];
                //이 변수는 이 줄에 들어갈 <td>(테이블 칸)들을 임시로 담을 배열.
                // 나중에 이 배열을 $tdList에 넣어 2차원 배열처럼 관리할 거야.

                for(let j=0; j<size; j++) {
                    let $td = document.createElement("td");
                    $td.addEventListener("click", clickEvent);
                    $td.innerText = frontList[i][j];
                    $td.style.backgroundColor = "coral";
                   
                    $tr.append($td);
                    $tempTdList.push($td);
                }
               
                $tdList.push($tempTdList);
                $table.append($tr);
            }
            $center.append($table);
        }
//--------------------------------------------------------
        function setTimer() {
            time += 1;
            document.querySelector("#timer").innerText = time;
        }
//------------------------------------------------------------
        function clickEvent() {
            //1. 클릭한 위치 찾기 (y, x 좌표 찾기)
            let y = 0;
            let x = 0;
            for(let i=0; i<size; i++) {
                for(let j=0; j<size; j++) {
                    if(this == $tdList[i][j]) {
                        //this는 현재 클릭한 <td> 요소를 가리켜.
                        // 2중 반복문으로 $tdList 이차원 배열에서 클릭한 <td>가 어디 위치인지 (i, j) 찾는 거야.
                        // 찾아서 y, x에 그 위치 인덱스를 저장해.
                        // 이렇게 좌표를 알면, 나중에 그 위치에 해당하는 값을 frontList나 backList에서 쉽게 찾을 수 있어.
                        y = i;
                        x = j;
                        break;
                    }
                }
            }
            //-----------------------------------------------
            //2. 클릭한 셀에 적힌 숫자가 현재 게임 목표 숫자인지 검사
            if(this.innerText == gameNum) {
                //클릭한 셀의 숫자(innerText)가 현재 진행 중인 gameNum과 같을 때만 다음 동작을 해.
                // 예를 들어, 지금 gameNum이 1이라면, 1이 적힌 셀만 반응하는 거지.
                if(1 <= gameNum && gameNum <= size*size) {
                    //3. 클릭한 숫자가 1 이상 size*size 이하일 때 (초기 숫자 범위)
                    if(gameNum == 1) {
                        timeId = setInterval(setTimer, 1000);  //이건 시간 가는 함수?
                    }
                    this.innerText = backList[y][x];
                    this.style.backgroundColor = "antiquewhite";
                } else {
                    this.innerText = "";
                    this.style.backgroundColor = "";

                    this.style.cursor = "default";
                }
                //만약 gameNum이 1부터 9 (3x3 게임이니까 size*size=9) 사이면,
                // 게임 첫 숫자(1)를 클릭하면 타이머가 시작돼. setInterval이 setTimer 함수를 1초마다 호출해서 시간 흐르게 만드는 부분.
                // 그리고 클릭한 셀에 backList[y][x]에 있는 숫자로 숫자가 바뀌어.
                // 배경색도 바뀌어서 (antiquewhite) 클릭한 셀이 시각적으로 달라짐.
                // 반면에 gameNum이 10 이상이면,
                // 클릭한 칸을 빈칸으로 바꾸고, 배경색, 커서도 기본 상태로 바꿔.
                // 즉, 더 이상 보여줄 숫자가 없을 때는 빈칸 처리하는 거야.

                //4. 게임 진행 숫자 증가 및 화면 갱신
                gameNum += 1;

                document.querySelector("#nextNum").innerText = gameNum;
                //gameNum을 1 증가시켜서 다음에 찾아야 할 숫자를 업데이트.
                // 그리고 화면에 보이는 다음 숫자 표시(nextNum 요소의 텍스트)를 바꿔줌.
            }
            //5. 게임 종료 체크
            gameOver();
            //클릭 후마다 게임이 끝났는지 판단하는 함수 gameOver()를 호출해.
            // 보통 이 함수는 목표 숫자가 끝까지 다 선택됐는지 체크해서, 끝나면 타이머 정지하고 알림을 띄워주는 역할을 함.
        }
//------------------------------------------------------------------------------
        function hintClick() {
            let y = 0;
            let x = 0;
            //우선 y, x 변수를 만들어서, 현재 목표 숫자의 위치를 저장할 준비를 해.

            //2중 반복문으로 위치 찾기
            for(let i=0; i<size; i++) {
                for(let j=0; j<size; j++) {
                    if($tdList[i][j].innerText == gameNum) {
                        y = i;
                        x = j;
                        break;
                    }
                }
            }
            //이중 반복문으로 테이블의 모든 셀($tdList[i][j])을 확인해.
            //각 셀의 innerText (보여지는 숫자)를 확인해서, 지금 클릭해야 하는 숫자(gameNum)와 같은 셀을 찾는다.
            // 찾았다면, 그 위치를 y, x에 저장하고 바로 반복문을 빠져나온다.

            $tdList[y][x].style.backgroundColor = "red";
        }
    //--------------------------------------------------------
        function clearTable() {
            $center.removeChild($table );
             // 테이블을 center에서 제거함
            //이렇게 함축된 함수를 뭐라고 함?
            //이건 DOM 조작 메서드예요.
            // $center는 <div id="center">이고,
            // $table은 JavaScript에서 만든 <table> 요소입니다.
            // 즉👉 “#center라는 부모 요소 안에서 자식 요소인 table을 제거해라” 라는 뜻이에요.

            //removeChild()는 함수 맞아요!
            //removeChild()는 자바스크립트의 DOM API 함수입니다.
            // 노드를 동적으로 제거할 때 사용돼요.
            //당신이 말한 “이렇게 함축된 함수”는 DOM API 함수 또는 빌트인 메서드라고 부릅니다.
        }
        //-------------------------------------------------
        //replayClick() 함수는 "Replay" 버튼을 클릭했을 때 실행되는 함수로, 게임을 초기화하고 다시 시작하는 역할
        function replayClick() { //리플라이 버튼을 누르면
            clearInterval(timeId); //타이머 정지
            clearTable(); // 테이블 지우기  화면에 있는 테이블 삭제

            // 변수 초기화
            gameNum = 1;      
            time = 0;    
            timeId = null;
            frontList = [];
            backList = [];
            $table = document.createElement("table");;
            $tdList = [];
           
            //화면에 보이는 숫자 초기화
            document.querySelector("#timer").innerText = time;
            document.querySelector("#nextNum").innerText = gameNum;

            init(); //다시 시작
        }
        //---------------------------------------------------------
        //게임오버를 판단하는것 .
        function gameOver() {
            if(gameNum > size*size*2) { //마지막 숫자는 게임오버
                clearInterval(timeId); //멈춤

                // 게임 종료 화면
                alert("게임을 종료합니다!");
            }
        }

    </script>

</body>
</html>
반응형