라라리라

2023.10.17 / Step 6 [DOM_테트리스] - 코딩 70 일차 본문

코딩/2023 JavaScript DOM

2023.10.17 / Step 6 [DOM_테트리스] - 코딩 70 일차

헤실 2023. 10. 17. 17:47
<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Tetris Game</title>

    <style>
        #center {
            margin: 0 auto;
            text-align: center;
        }
        #myTetris {
            border-collapse: collapse;
        }
        #myTetris td {
            width: 30px;
            height: 30px;
        }
        #tetnext {
            margin: 0 auto;
            border-collapse: collapse;
            text-align: left;
            vertical-align: top;
        }
        #tet td {
            border: 1px solid black;
            width: 50px;
            height: 30px;
        }
        #nextblock {
            border-collapse: collapse;
        }
        #nextblock td {
            width: 30px;
            height: 30px;
            border: 1px solid black;
        }
        .gray    { background-color: #3a3a3a; }
        .green   { background-color: green; }
        .red     { background-color: red; }
        .purple  { background-color: purple; }
        .orange  { background-color: orange; }
        .blue    { background-color: blue; }
        .yellow  { background-color: yellow; }
        .skyblue { background-color: skyblue; }
        .white   { background-color: black; }
    </style>

</head>
<body>
    <table id="center">
        <tr>
            <td>
                <h1>테트리스</h1>
            </td>
        </tr>
        <tr>
            </td>
            <td id="tetrisCenter"></td>
            <td id="tetnext">
                <h3>TETRIS</h3>
                <h4 id="tetscore">Score : 0</h4>
                <h4 id="tetlv">Level : 0</h4>
                <h4 id="tetline">Line : 0</h4>
                <td id="nextblock">
                   
                </td>
            </td>
        </tr>
    </table>

    <script>
        let col = 12;
        let row = 22;
        let $data = [];
        let $center = document.querySelector(`#tetrisCenter`);
        let $table = document.createElement(`table`);
        let $tr = document.createElement(`tr`);
        let $td = document.createElement(`td`);
        let colorList = ["white", "green", "red", "purple", "orange", "blue", "yellow", "skyblue", "gray", ""];
        const GRAY = 8;
        const WHITE = 0;
        const BLACK = 9;
        const BLOCK = GRAY;
        let Gameover = false;
        let myInterval = null;
        let curY = 0; //블록생성 Y좌표
        let curX = 0; //블록생성 X좌표
        let curblock = null; //현재 블록의 정보
        let nextblock = null;
        let line = 0;
        let blockList = [
    {
        name: "s",
        color: 1,
        shape:
            [
                [0, 0, 0],
                [0, 1, 1],
                [1, 1, 0]
            ]
    },
    {
        name: "z",
        color: 2,
        shape:
            [
                [0, 0, 0],
                [1, 1, 0],
                [0, 1, 1]
            ]
    },
    {
        name: "t",
        color: 3,
        shape:
            [
                [0, 0, 0],
                [1, 1, 1],
                [0, 1, 0]
            ]
    },
    {
        name: "l",
        color: 4,
        shape:
            [
                [0, 1, 0],
                [0, 1, 0],
                [0, 1, 1]
            ]
    },
    {
        name: "j",
        color: 5,
        shape:
            [
                [0, 1, 0],
                [0, 1, 0],
                [1, 1, 0]
            ]
    },
    {
        name: "o",
        color: 6,
        shape:
            [
                [1, 1],
                [1, 1]
            ]
    },
    {
        name: "i",
        color: 7,
        shape:
            [
                [0, 0, 0, 0],
                [1, 1, 1, 1],
                [0, 0, 0, 0],
                [0, 0, 0, 0],
            ]
    }
];

        function init(){
            $table = document.createElement(`table`)
            $table.id = `myTetris`;
        for(let i = 0; i < row; i++){
            $tr = document.createElement(`tr`);
            $temp = [];
            for(let j = 0; j < col; j++){
            $td = document.createElement(`td`);
            $temp.push(WHITE);
            $tr.append($td);
            }
            $data.push($temp)
            $table.append($tr);
        }    
        $center.append($table);
        $table = document.querySelector(`#myTetris`);
        for(let i = 0 ; i < col; i++){
        $data[0][i] = GRAY
        $data[row - 1][i] = GRAY
        $table.children[0].children[i].setAttribute(`class`, `gray`);
        $table.children[row - 1].children[i].setAttribute(`class`, `gray`);
    }
        for(let i = 0 ; i < row; i++){
        $data[i][0] = GRAY
        $data[i][col - 1] = GRAY
        $table.children[i].children[0].setAttribute(`class`, `gray`);
        $table.children[i].children[col - 1].setAttribute(`class`, `gray`);
    }
        for(let i = 0; i < row; i++){
            for(let j = 0; j < col; j++){
                //$table.children[i].children[j].innerText = $data[i][j];
            }
        }
        let $nextblock = document.querySelector(`#nextblock`)
        $table = document.createElement(`table`)
        $table.id = `nextIndex`
        for(let i = 0; i < 4; i++){  //넥스트만들기
            $tr = document.createElement(`tr`);
            for(let j = 0; j < 4; j++){
            $td = document.createElement(`td`);
            $tr.append($td);
            }
            $table.append($tr);
        }
        $nextblock.append($table);
       
    myInterval = setInterval(Gameplay, 500)
        }
        window.addEventListener(`keydown`, (a)=>{ //테트리스창에 키다운 이벤트생성
        let key = a.code; //key는 입력값
        if(key == `ArrowLeft`) Left(); //왼쪽화살표 == Left();함수실행
        else if(key == `ArrowRight`) Right(); //오른쪽화살표 == Right(); 함수실행
        else if(key == `ArrowDown`) { //아래쪽화살표 == Down()함수의 값이 false면 NewBlock함수실행
            if(Down() == false){
                lineClear();
                NewBlock();
                fn_cleannext()
                fn_nextblock()
            }
        }
       else if(key == `Space`) {
           while(Down()){}//Down함수를 반복실행(return값으로 False를 받을때까지)
            if(Down() == false){
            lineClear();
            NewBlock(); //리턴값이 False가 나올때까지 실행하였으므로(바닥이나 다른블록에 닿을때까지) 새 블록을 만든다.
            fn_cleannext()
            fn_nextblock()
        }
       }
       else if(key == `ArrowUp`) Rotate();
       print();
    })
    function fn_nextblock(){
        let nextId = document.querySelector(`#nextIndex`);
        let r = Math.floor(Math.random() * blockList.length);
        nextblock = blockList[r];
        let shape = nextblock.shape;
        let colorindex = nextblock.color;
        for(let i = 0; i < shape.length; i++){
            for(let j = 0; j < shape[i].length; j++){
                if(shape[i][j] == 1){
                nextId.children[i].children[j].setAttribute(`class`, colorList[colorindex])
                }
            }
        }
    }
    function fn_cleannext(){
        let nextId = document.querySelector(`#nextIndex`);
        for(let i = 0; i < 4; i++){
            for(let j = 0; j < 4; j++){
                nextId.children[i].children[j].removeAttribute(`class`, colorList[0])
            }
        }
    }
    function NewBlock(){ //블록생성
        curY = 1; //블록생성위치Y값을 1로 지정
        curX = 4; //블록생성위치X값을 4로 지정

        curblock = nextblock //blockList[r]을 현재 블록정보에 저장
        fn_Gameover();
        let shape = curblock.shape; // 현재블록(curblock)의 모양을 shape변수로 지정
        for(let y = 0; y < shape.length; y++){
            for(let x = 0; x < shape[y].length; x++){ //현재블록의 모양(shape)만큼 반복문
                if(shape[y][x] == 1){ //블록모양의 값에서 1인 부분 (0, 1)
                    $data[curY + y][curX + x] = nextblock.color //블록생성위치의 데이터값에 블록리스트[r]의 색깔값을 입력
                }
            }
        }
        print();
       
    }
    function print(){ //화면에 $data내용대로 출력
        $table = document.querySelector(`#myTetris`) //$table = myTetris
        $tetline = document.querySelector(`#tetline`)
        $tetscore = document.querySelector(`#tetscore`)
        $tetlv = document.querySelector(`#tetlv`);
        for(let i = 0; i < row; i++){
            for(let j = 0; j < col; j++){
            // $table.children[i].children[j].innerText = $data[i][j]; //table 안의 텍스트값 = $data값  
              if($data[i][j] != BLACK ){
              $table.children[i].children[j].setAttribute(`class`, colorList[$data[i][j]]) //$data값과 동일하게 class 지정
            }
            }
        }
        $tetline.innerHTML = `Line : ${line}`
        $tetscore.innerHTML = `Score : ${line * 1000}`
        $tetlv.innerHTML = `Level : ${parseInt(line / 10) + 1}`
    }
    function BlockIndex(shape){ //블록인덱스(shape값)함수
        let temp = []; //임시배열
        for(let i = 0; i < shape.length; i++){
            for(let j = 0; j < shape[i].length; j++){
                if(shape[i][j] == 1){ //shape에서 1인 index를 임시배열에 저장
                    temp.push([i + curY, j + curX]);
                }
            }
        }
        return temp;
    }
    function Movable(BlockIndex, nextY, nextX){ //Movable 함수지정(blockIndex, 다음Y값, 다음X값)
        for(let i = 0; i < BlockIndex.length; i++){ //BlockIndex 배열의 길이만큼 반복
            let y = BlockIndex[i][0]; //Y = 블록인덱스[i]의 Y값
            let x = BlockIndex[i][1]; //X = 블록인덱스[j]의 X값
            if($data[y + nextY][x + nextX] >= BLOCK){ //블록인덱스[i]의 Y값 , nextY 블록인덱스[i]의 X값이 BLOCK(8)보다 크거나 같을경우(크면 9=BLACK)
                return false; //false를 리턴한다
            }
        }
        return true;
    }
    function Left(){
        let nextY = 0; //좌측버튼을 눌렀을때 변하게 될 Y값
        let nextX = -1; //좌측버튼을 눌렀을때 변하게 될 X값
        let shape = curblock.shape; //현재블록의 모양을 shape변수에 저장
        let Index = BlockIndex(shape); //현재블록의 index값을 리턴받음
        let move = Movable(Index, nextY, nextX); //현재블록의 index값에 이동시킬 Y X값을 적용시켜 이동이 가능한지 True False로 알려줌
        if(move == true){
        Update(Index, 0, 0, WHITE);
        Update(Index, nextY, nextX, curblock.color);
        curX--;
        }
    }
    function Right(){
        let nextY = 0; //좌측버튼을 눌렀을때 변하게 될 Y값
        let nextX = 1; //좌측버튼을 눌렀을때 변하게 될 X값
        let shape = curblock.shape; //현재블록의 모양을 shape변수에 저장
        let Index = BlockIndex(shape); //현재블록의 index값을 리턴받음
        let move = Movable(Index, nextY, nextX); //현재블록의 index값에 이동시킬 Y X값을 적용시켜 이동이 가능한지 True False로 알려줌
        if(move == true){
        Update(Index, 0, 0, WHITE);
        Update(Index, nextY, nextX, curblock.color);
        curX++;
        }
    }
    function Down(){
        let nextY = 1; //좌측버튼을 눌렀을때 변하게 될 Y값
        let nextX = 0; //좌측버튼을 눌렀을때 변하게 될 X값
        let shape = curblock.shape; //현재블록의 모양을 shape변수에 저장
        let Index = BlockIndex(shape); //현재블록의 index값을 리턴받음
        let move = Movable(Index, nextY, nextX); //현재블록의 index값에 이동시킬 Y X값을 적용시켜 이동이 가능한지 True False로 알려줌
        if(move == true){
        Update(Index, 0, 0, WHITE);
        Update(Index, nextY, nextX, curblock.color);
        curY++;
        } else if (move == false){
            Update2(Index, 0, 0, curblock.color);
        }
        return move;
    }
    function Rotate(){
        let shape = curblock.shape;
        let tempshape = [];
        let OldIndex = BlockIndex(shape);
        for(let i = 0; i < shape.length; i++){
            let temp = [];
            for(let j = 0; j < shape[i].length; j++){
                temp.push(shape[shape.length -1 -j][i])
            }
            tempshape.push(temp);
        }
        let Index = BlockIndex(tempshape);
        let move = Movable(Index, 0, 0);
        if(move == true){
        Update(OldIndex, 0, 0, WHITE);
        Update(Index, 0, 0, curblock.color);
        curblock.shape = tempshape;
        console.log(curblock.shape);
    }
    }    
    function Update(BlockIndex, inputY, inputX, color){  //BlockIndex에서 반환받은 temp배열과 입력받은Y값, 입력받은X값, 지정색
        for(let i = 0; i < BlockIndex.length; i++){ //BlockIndex의 Temp배열의 길이만큼 반복
            let y = BlockIndex[i][0]; //Y = 블록인덱스[i]의 Y값
            let x = BlockIndex[i][1]; //X = 블록인덱스[i]의 X값
            $data[y + inputY][x + inputX] = color; //블록인덱스[i]의 Y,X값 + 입력받은Y,X값의 데이터를 지정받은 색상의 값으로 변경
        }  
    }
    function Update2(BlockIndex, inputY, inputX, color){  //BlockIndex에서 반환받은 temp배열과 입력받은Y값, 입력받은X값, 지정색
        for(let i = 0; i < BlockIndex.length; i++){ //BlockIndex의 Temp배열의 길이만큼 반복
            let y = BlockIndex[i][0]; //Y = 블록인덱스[i]의 Y값
            let x = BlockIndex[i][1]; //X = 블록인덱스[i]의 X값
            $data[y + inputY][x + inputX] = BLACK; //블록인덱스[i]의 Y,X값 + 입력받은Y,X값의 데이터를 지정받은 색상의 값으로 변경
            $table.children[y + inputY].children[x + inputX].setAttribute(`class`, colorList[curblock.color])
        }  
    }
    function lineClear(){
        let delID = [];
        for(let i = 1; i < row - 1; i++){
            let count = 0;
            for(let j = 1; j < col - 1; j++){
                if($data[i][j] != WHITE){
                    count++;
                }
            }
            if(count == 10){
                delID.push(i);
                line++;
            }
        }
        for(let i = 0; i < delID.length; i++){
            $data.splice(delID[i], 1);
            $data.splice(0, 1);
            $data.unshift([BLOCK,WHITE,WHITE,WHITE,WHITE,WHITE,WHITE,WHITE,WHITE,WHITE,WHITE,BLOCK]);
            $data.unshift([BLOCK,BLOCK,BLOCK,BLOCK,BLOCK,BLOCK,BLOCK,BLOCK,BLOCK,BLOCK,BLOCK,BLOCK]);
        }
    }
    function Gameplay(){
        if(Gameover == true){
            clearInterval(myInterval);
            alert(`패배!! 게임을 종료합니다.`)
            restart();
        }
        if(Down() == false){
            if(Down() == false){
                lineClear();
                NewBlock();
            }
        }
        print();
       
    }
    function fn_Gameover(){
        let block = BlockIndex(curblock.shape);
        for(let i = 0; i < block.length; i++){
            if($data[block[i][0]][block[i][1]] == 9 ){
                Gameover = true;
                break;
            }
        }
        console.log(Gameover);
        return Gameover;
    }
    function restart(){
        $nextblock = document.querySelector(`#nextblock`);
        $table = document.querySelector(`#myTetris`);
        $table.remove();
        $data = [];
        Gameover = false;
        myInterval = null;
        curY = 0; //블록생성 Y좌표
        curX = 0; //블록생성 X좌표
        curblock = null; //현재 블록의 정보
        $nextblock.remove();
        init();
        fn_nextblock();
        NewBlock();
    }

        init();
        fn_nextblock()
        NewBlock();
     

    </script>
</body>
</html>

 

Tetris Game

테트리스

TETRIS

Score : 0

Level : 0

Line : 0