자바스크립트 2048게임

banhogu·2023년 5월 31일
0
<html>

<head>
    <meta charset="UTF-8">
    <title>2048</title>
    <style>
        #table {
            border-collapse: collapse;
            user-select: none;
        }

        #table td {
            border: 10px solid #bbada0;
            width: 116px;
            height: 128px;
            font-size: 50px;
            font-weight: bold;
            text-align: center;
        }

        #score {
            user-select: none;
        }

        .color-2 {
            background-color: #eee4da;
            color: #776e65;
        }

        .color-4 {
            background-color: #eee1c9;
            color: #776e65;
        }

        .color-8 {
            background-color: #f3b27a;
            color: 'white';
        }

        .color-16 {
            background-color: #f69664;
            color: 'white';
        }

        .color-32 {
            background-color: #f77c5f;
            color: 'white';
        }

        .color-64 {
            background-color: #f75f3b;
            color: 'white';
        }

        .color-128 {
            background-color: #edd073;
            color: #776e65;
        }

        .color-256 {
            background-color: #edcc62;
            color: #776e65;
        }

        .color-512 {
            background-color: #edc950;
            color: #776e65;
        }

        .color-1024 {
            background-color: #edc53f;
            color: #776e65;
        }

        .color-2048 {
            background-color: #edc22e;
            color: #776e65;
        }
    </style>
</head>

<body>
    <table id="table"></table>
    <div><button>되돌리기</button></div>
    <script>
        const $table = document.getElementById('table');
        let $button = document.querySelector('button')
        let data = [];
        let startCoord;
        let history = []

        function random2cell() {
            let empty = []
            data.forEach((rowel, idx) => {
                rowel.forEach((cellel, jdx) => {
                    if (!cellel) {
                        empty.push([idx, jdx])
                    }
                })
            })
            let random = empty[Math.floor(Math.random() * empty.length)]
            data[random[0]][random[1]] = 2
        }
        function drawcell() {
            data.forEach((rowel, i) => {
                rowel.forEach((cellel, j) => {
                    let target = $table.children[i].children[j]

                    if (cellel > 0) {
                        target.textContent = cellel
                        target.className = 'color-' + cellel

                    }
                    else {
                        target.textContent = ''
                        target.className = ''
                    }
                })
            })
        }

        function startGame() {
            for (let i = 0; i < 4; i++) {
                let $tr = document.createElement('tr')
                let rowdata = []
                for (let j = 0; j < 4; j++) {
                    let $td = document.createElement('td')
                    $tr.append($td)
                    rowdata.push(0)
                }
                data.push(rowdata)
                $table.append($tr)
            }

            random2cell()
            drawcell()
        }

        $button.addEventListener('click',()=>{
            let predata = history.pop()
            if(!predata){
                return
            }
            data = predata
            drawcell()
        })
        function clear() {
            data = []
            for (let i = 0; i < 4; i++) {
                for (let j = 0; j < 4; j++) {
                    $table.innerHTML = ''
                }
            }
            startGame()
        }

        window.addEventListener('keyup', (event) => {
            if (event.key === 'ArrowUp') {
                moveCells('up');
            } else if (event.key === 'ArrowDown') {
                moveCells('down');
            } else if (event.key === 'ArrowLeft') {
                moveCells('left');
            } else if (event.key === 'ArrowRight') {
                moveCells('right');
            }
        });

        function moveCells(direction) {
            let historydata = JSON.parse(JSON.stringify(data))
            history.push(historydata)

            switch (direction) {
                case 'left': {
                    let newdata = [[], [], [], []]
                    data.forEach((rowdata, i) => {
                        rowdata.forEach((celldata, j) => {
                            if (celldata) {
                                let currentrow = newdata[i]
                                let preventcell = currentrow[currentrow.length - 1]
                                if (preventcell === celldata) {
                                    currentrow[currentrow.length - 1] *= -2
                                }
                                else {
                                    newdata[i].push(celldata)
                                }


                            }
                        })
                    });
                    [1, 2, 3, 4].forEach((rowel, i) => {
                        [1, 2, 3, 4].forEach((cellel, j) => {
                            data[i][j] = Math.abs(newdata[i][j]) || 0;
                        })
                    })
                    break;
                }
                case 'right': {
                    let newdata = [[], [], [], []]
                    data.forEach((rowdata, i) => {
                        rowdata.forEach((celldata, j) => {
                            if (rowdata[3 - j]) {
                                let currentrow = newdata[i]
                                let preventcell = currentrow[currentrow.length - 1]
                                if (preventcell === rowdata[3 - j]) {
                                    currentrow[currentrow.length - 1] *= -2
                                }
                                else {
                                    newdata[i].push(rowdata[3 - j])
                                }
                            }
                        })
                    });
                    [1, 2, 3, 4].forEach((rowel, i) => {
                        [1, 2, 3, 4].forEach((cellel, j) => {
                            data[i][3 - j] = Math.abs(newdata[i][j]) || 0;
                        })
                    })
                    break;
                }
                case 'up': {
                    let newdata = [[], [], [], []]
                    data.forEach((rowdata, i) => {
                        rowdata.forEach((celldata, j) => {
                            if (celldata) {
                                let currentrow = newdata[j]
                                let preventcell = currentrow[currentrow.length - 1]
                                if (preventcell === celldata) {
                                    currentrow[currentrow.length - 1] *= -2
                                }
                                else {
                                    newdata[j].push(celldata)
                                }
                            }
                        })
                    });
                    [1, 2, 3, 4].forEach((rowel, i) => {
                        [1, 2, 3, 4].forEach((cellel, j) => {
                            data[j][i] = Math.abs(newdata[i][j]) || 0;
                        })
                    })
                    break;
                }
                case 'down': {
                    const newData = [[], [], [], []];
                    data.forEach((rowData, i) => {
                        rowData.forEach((cellData, j) => {
                            if (data[3 - i][j]) {
                                const currentRow = newData[j];
                                const prevData = currentRow[currentRow.length - 1];
                                if (prevData === data[3 - i][j]) {
                                    currentRow[currentRow.length - 1] *= -2;
                                } else {
                                    newData[j].push(data[3 - i][j]);
                                }
                            }
                        });
                    });
                    console.log(newData);
                    [1, 2, 3, 4].forEach((cellData, i) => {
                        [1, 2, 3, 4].forEach((rowData, j) => {
                            data[3 - j][i] = Math.abs(newData[i][j]) || 0;
                        });
                    });
                    break;
                }
            }
            if (data.flat().includes(2048)) {
                drawcell()
                setTimeout(() => {
                    alert('축하합니다 승리했습니다')
                }, 50);
                setTimeout(() => {
                    clear()
                }, 1000);
            }
            else if (!data.flat().includes(0)) {
                setTimeout(() => {
                    alert('게임오버')
                }, 50);
                setTimeout(() => {
                    clear()
                }, 1000);
            }
            else {
                random2cell()
                drawcell()
            }
        }

        window.addEventListener('mousedown', (event) => {
            startCoord = [event.clientX, event.clientY];
        });
        window.addEventListener('mouseup', (event) => {
            const endCoord = [event.clientX, event.clientY];
            const diffX = endCoord[0] - startCoord[0];
            const diffY = endCoord[1] - startCoord[1];
            if (diffX < 0 && Math.abs(diffX) > Math.abs(diffY)) {
                moveCells('left');
            } else if (diffX > 0 && Math.abs(diffX) > Math.abs(diffY)) {
                moveCells('right');
            } else if (diffY > 0 && Math.abs(diffX) <= Math.abs(diffY)) {
                moveCells('down');
            } else if (diffY < 0 && Math.abs(diffX) <= Math.abs(diffY)) {
                moveCells('up');
            }
        });
        startGame()
    </script>
</body>

</html>

키보드나 마우스에 이벤트를 걸고 위아래좌우로 움직이면서 숫자를 쌓아 2048을 만드는 게임이다. 테이블에 tr,td를 그리고 그에 맞게 data를 맞춰주고, 이벤트 동작에 맞게 숫자를 더해간다. 이벤트 발생 시 랜덤으로 2를 추가해주는 함수를 넣어줬다.
up과 down 이벤트가 많이 어려웠는데 a4에 임의 데이터를 써가며 로직을 이해하며 코드를 작성했다.

profile
@banhogu

0개의 댓글