zoukankan      html  css  js  c++  java
  • 动手学Javascript(1)——PopStar

    PopStar是一款很流行的手机游戏。它的基本规则是在某个方块上单击,如果该方块周围有和它颜色一样的方块,那么这些方块都被选中。之后在选中方块的某一个上再次单击,所有选中的方块就会消失。

    如下图所示,7个绿色的方块被选中(选中的方块被白色的框包围):


    在选中的方块再次单击,这些绿色的方块就会消失。如果这些方块的上方就其他方块,上方的方块会掉下来。如果某一列全被消失,那么右边的列会自动左移。7块选中的绿色方块消失之后的效果如下图所示:


    HTML代码如下所示:

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset=utf-8 />
            <title>PopStar</title>
            <link rel="stylesheet" href="http://code.jquery.com/ui/1.10.3/themes/smoothness/jquery-ui.css" />
            <script src="http://code.jquery.com/jquery-1.9.1.js"></script>
            <script src="http://code.jquery.com/ui/1.10.3/jquery-ui.js"></script>
            <script src="PopStar.js" type="text/javascript">
            </script>
            <link rel="stylesheet" type="text/css" href="PopStar.css" />
        </head>
        <body>
            <h1>Welcome to PopStar</h1>
            <div id="totalScore">Total Score: 0</div>
            <div id="currentScore">Click to Select.</div>
            <div id="mainCanvas">
            </div>
            <div id="notification">
                <div id="message"></div>
            </div>
        </body>
    </html>

    从上述代码可以看出,我们将会用到JQuery及jQuery UI的相关功能。

    CSS的代码如下所示:

    #mainCanvas {
        background-color: black;
         300px;
        height: 300px;
    }
    
    .block {
        position: fixed;
        height: 28px;
         28px;
        border-radius: 4px;
    }
    
    .selected {
        height: 26px;
         26px;
        border-color: white;
        border-style: solid;
        border- 1px;
    }

    CSS主要定义了游戏的背景,以及方块(选中或未选中)的外观。

    游戏的功能主要用Javascript实现,如下所示:

    $(document).ready(function () {
        var sharedData;
        initGame();
        startGame();
    
        function initGame() {
            sharedData = {};
            sharedData.size = 10;
    
            var canvas = $('#mainCanvas');
            var width = parseInt(canvas.css('width'));
            var height = parseInt(canvas.css('height'));
            if (width != height) {
                alert('the canvas should be a square.');
            }
            sharedData.canvas = canvas;
            sharedData.blockLength = width / sharedData.size;
            sharedData.matrix = initMatrix();
    
            $('#notification').dialog({
                 400,
                resizable: false,
                modal: true,
                buttons: [{ text: "Ok", click: function () { $(this).dialog("close"); location.reload(); } }]
            });
        }
    
        function startGame() {
            sharedData.size = 10;
            sharedData.status = 0; // possible values: 0, 1
            sharedData.totalScore = 0;
    
            clearMatrix();
    
            initBlocks(sharedData);
            moveBlocks();
    
            clearCurrentScore();
            clearTotalScore();
            hideNotification();
    
            if (isGameOver()) {
                showNotification();
            }
        }
    
        function initBlocks(data) {
            var size = data.size;
            var row, col, value;
            var singleColor = size * size / 4;
            var divString;
            var newRow, newCol, index;
    
            $('.block').each(function () {
                $(this).remove();
            });
    
            var randomArray = getRandomArray(data.size);
    
            for (row = 0; row < size; ++row) {
                for (col = 0; col < size; ++col) {
                    if (row * size + col < singleColor) {
                        value = 1;
                    }
                    else if (row * size + col < singleColor * 2) {
                        value = 2;
                    }
                    else if (row * size + col < singleColor * 3) {
                        value = 3;
                    }
                    else {
                        value = 4;
                    }
                    
                    index = randomArray[row * size + col];
                    newRow = Math.floor(index / size);
                    newCol = index % size;
    
                    divString = '<div class="block" currow="0" curcol="0" nextrow="' + newRow.toString()
                        + '" nextcol="' + newCol.toString() + '" value="' + value.toString() + '"></div>';
                    $('#mainCanvas').append(divString);
                }
            }
        }
    
        function getRandomArray(size) {
            var total = size * size;
            var array = new Array(total);
            var i, index, temp;
            
            for (i = 0; i < array.length; ++i) {
                array[i] = i;
            }
            
            for (i = array.length - 1; i > 0; --i) {
                index = Math.floor(Math.random() * total);
    
                temp = array[i];
                array[i] = array[index];
                array[index] = temp;
            }
            
            return array;
        }
    
        function moveBlocks() {
            $('.block').each(function () {
                var nextRow = $(this).attr('nextrow');
                var nextCol = $(this).attr('nextcol');
                var value = $(this).attr('value');
                var parentPos = $(this).parent().offset();
                var top = parseInt(nextRow) * sharedData.blockLength + parentPos.top + 1;
                var left = parseInt(nextCol) * sharedData.blockLength + parentPos.left + 1;
                var cssTop = top.toString() + 'px';
                var cssLeft = left.toString() + 'px';
                var colors = ['#aaaaaa', '#3333cc', '#33cc33', '#cc3333', '#cccc33'];
    
                $(this).animate({
                    top: cssTop,
                    left: cssLeft
                },
                500);
    
                $(this).css({
                    'background-color': colors[parseInt(value)]
                });
    
                $(this).attr('currow', nextRow);
                $(this).attr('curcol', nextCol);
            });
        }
    
        $('.block').click(function () {
            var clickedBlock = getClickedBlockPos($(this));
            var sameColorBlocks;
    
            clearMatrix();
            sameColorBlocks = getBlocksWithSameColor(clickedBlock.row, clickedBlock.col);
            updateStatus(clickedBlock.row, clickedBlock.col, sameColorBlocks);
        });
    
        function updateStatus(row, col, sameColorBlocks) {
            if (sameColorBlocks.length > 1) {
                if (sharedData.status == 0) {
                    sharedData.status = 1;
                    setSelectedBlocks(sameColorBlocks);
                }
                else {
                    if (isClickAgain(row, col, sameColorBlocks)) {
                        moveMatrix(sharedData.matrix, sameColorBlocks);
                        sharedData.status = 0;
                        updateTotalScore(sharedData, sameColorBlocks.length);
                        clearSelectedBlocks();
                        moveBlocks();
    
                        clearMatrix();
                        if (isGameOver()) {
                            showNotification();
                        }
                    }
                    else {
                        setSelectedBlocks(sameColorBlocks);
                    }
                }
            }
            else if (sharedData.status == 1) {
                sharedData.status = 0;
                clearSelectedBlocks();
            }
        }
    
        function moveMatrix(matrix, sameColorBlocks) {
            moveMatrixDown(matrix, sameColorBlocks);
            moveMatrixLeft(matrix);
            deleteBlocks();
            updateBlockPosition();
        }
    
        function updateBlockPosition() {
            $('.block').each(function () {
                var curRow = parseInt($(this).attr('currow'));
                var curCol = parseInt($(this).attr('curcol'));
    
                var moveDown = sharedData.matrix[curRow][curCol].moveDown;
                var moveLeft = sharedData.matrix[curRow][curCol].moveLeft;
    
                var nextRow = curRow + moveDown;
                var nextCol = curCol - moveLeft;
    
                $(this).attr('nextrow', nextRow.toString());
                $(this).attr('nextcol', nextCol.toString());
            });
        }
    
        function deleteBlocks() {
            $('.block').each(function () {
                var curRow = parseInt($(this).attr('currow'));
                var curCol = parseInt($(this).attr('curcol'));
        
                if (sharedData.matrix[curRow][curCol].value == 0) {
                    $(this).remove();
                }
            });
        }
    
        function moveMatrixDown(matrix, toBeDeleted) {
            var i, j;
    
            toBeDeleted.sort(sortPosition);
    
            for (i = 0; i < toBeDeleted.length; ++i) {
                matrix[toBeDeleted[i].row][toBeDeleted[i].col].value = 0;
    
                for (j = toBeDeleted[i].row ; j >= 0; --j) {
                    matrix[j][toBeDeleted[i].col].moveDown += 1;
                }
            }
        }
    
        function moveMatrixLeft(matrix) {
            for (i = 0; i < matrix.length; ++i) {
                if (isColumnBlank(matrix, i)) {
                    moveColumnsLeft(matrix, i);
                }
            }
        }
    
        function moveColumnsLeft(matrix, col) {
            var i, j;
            for(i = 0; i < matrix.length; ++i) {
                for (j = col + 1; j < matrix.length; ++j)
                    matrix[i][j].moveLeft += 1;
                }
        }
    
        function isColumnBlank(matrix, col) {
            var row;
            for (row = 0; row < matrix.length; ++row) {
                if (matrix[row][col].value != 0)
                    return false;
            }
    
            return true;
        }
    
        function sortPosition(pos1, pos2) {
            if ((pos1.col < pos2.col) || (pos1.col == pos2.col && pos1.row > pos2.row))
                return -1;
            if (pos1.col == pos2.col && pos1.row == pos2.row)
                return 0;
            return 1;
        }
    
        function setSelectedBlocks(sameColorBlocks) {
            $('.block').each(function () {
                if ($(this).hasClass('selected')) {
                    $(this).removeClass('selected');
                }
            });
    
            $('.block').each(function () {
                var curRow = parseInt($(this).attr('currow'));
                var curCol = parseInt($(this).attr('curcol'));
    
                if(isSelected(sameColorBlocks, curRow, curCol) && !$(this).hasClass('selected')) {
                    $(this).addClass('selected');
                }
            });
    
            setCurrentScore(sameColorBlocks.length);
        }
    
        function isSelected(sameColorBlocks, row, col) {
            for (var i = 0; i < sameColorBlocks.length; ++i) {
                if (sameColorBlocks[i].row == row && sameColorBlocks[i].col == col) {
                    return true;
                }
            }
    
            return false;
        }
    
        function clearSelectedBlocks() {
            $('.block').each(function () {
                if ($(this).hasClass('selected')) {
                    $(this).removeClass('selected');
                }
            });
    
            clearCurrentScore();
        }
    
        function getClickedBlockPos(block) {
            var curRow = parseInt(block.attr('currow'));
            var curCol = parseInt(block.attr('curcol'));
    
            return {
                row: curRow,
                col: curCol
            };
        }
    
        function initMatrix() {
            var i, j;
            var size = sharedData.size;
            var rows = new Array(size);
    
            for (i = 0; i < size; ++i) {
                rows[i] = new Array(size);
                for (j = 0; j < size; ++j) {
                    rows[i][j] = {
                        value: 0,
                        moveDown: 0,
                        moveLeft: 0
                    };
                }
            }
    
            return rows;
        }
    
        function clearMatrix() {
            var i, j;
            var size = sharedData.size;
            var matrix = sharedData.matrix;
    
            for (i = 0; i < size; ++i) {
                for (j = 0; j < size; ++j) {
                    matrix[i][j] = {
                        value: 0,
                        moveDown: 0,
                        moveLeft: 0
                    };
                }
            }
    
            $('.block').each(function () {
                var value = parseInt($(this).attr('value'));
                var curRow = parseInt($(this).attr('currow'));
                var curCol = parseInt($(this).attr('curcol'));
                sharedData.matrix[curRow][curCol].value = value;
            });
        }
    
        function getBlocksWithSameColor(row, col) {
            var matrix = sharedData.matrix;
            var value = matrix[row][col].value, curValue;
            var matrixSize = matrix[0].length;
            var visited = new Array();
            var top, curRow, curCol, preRow, preCol;
            var sameColor = new Array();
            var i;
    
            var flag = new Array(matrixSize * matrixSize);
            for (i = 0; i < flag.length; ++i) {
                flag[i] = false;
            }
    
            addBlockWithSameColor(matrix, visited, sameColor, flag, row, col);
    
            while (visited.length > 0) {
                top = visited.pop();
    
                // left
                curRow = top.row;
                curCol = top.col - 1;
                addBlockWhenWithSameColor(matrix, value, visited, sameColor, flag, curRow, curCol);
    
                // right
                curRow = top.row;
                curCol = top.col + 1;
                addBlockWhenWithSameColor(matrix, value, visited, sameColor, flag, curRow, curCol);
    
                // up
                curRow = top.row - 1;
                curCol = top.col;
                addBlockWhenWithSameColor(matrix, value, visited, sameColor, flag, curRow, curCol);
    
                // down
                curRow = top.row + 1;
                curCol = top.col;
                addBlockWhenWithSameColor(matrix, value, visited, sameColor, flag, curRow, curCol);
            }
    
            return sameColor;
        }
    
        function addBlockWithSameColor(matrix, visited, sameColor, flag, row, col) {
            var cell = {
                row: row,
                col: col
            };
    
            visited.push(cell);
            sameColor.push(cell);
            flag[row * matrix[0].length + col] = true;
        }
    
        function addBlockWhenWithSameColor(matrix, value, visited, sameColor, flag, curRow, curCol) {
            var matrixSize = matrix.length;
            var isOnBoundaryOrDiffColor = curRow >= 0 && curRow < matrixSize &&
                curCol >= 0 && curCol < matrixSize &&
                matrix[curRow][curCol].value == value;
            if (isOnBoundaryOrDiffColor && !flag[curRow * matrixSize + curCol]) {
                addBlockWithSameColor(matrix, visited, sameColor, flag, curRow, curCol);
            }
        }
    
        function isClickAgain(row, col, sameColor) {
            var result = false;
    
            $('.block').each(function () {
                var curRow = parseInt($(this).attr('currow'));
                var curCol = parseInt($(this).attr('curcol'));
    
                if(isSelected(sameColor, curRow, curCol) && $(this).hasClass('selected')) {
                    result = true;
                }
            });
    
            return result;
        }
    
        function setCurrentScore(num) {
            var score = getScore(num);
            $('#currentScore').html('Selection Score: ' + score.toString());
        }
    
        function clearCurrentScore() {
            $('#currentScore').html('Click to Slect.');
        }
    
        function clearTotalScore() {
            $('#totalScore').html('Total Score: 0');
        }
    
        function getScore(num) {
            return 5 * num * num;
        }
    
        function updateTotalScore(data, num) {
            var score = getScore(num);
            data.totalScore += score;
            $('#totalScore').html('Total Score: ' + data.totalScore.toString());
        }
    
        function hideNotification() {
            $('#notification').dialog('close');
        }
    
        function showNotification() {
            $('#message').html('Game over. Click Ok to restart.');
            $('#notification').dialog('open');
        }
    
        function isGameOver() {
            var over = true;
            var curRow, curCol;
            var sameColor;
    
            $('.block').each(function () {
                if (over) {
                    curRow = parseInt($(this).attr('currow'));
                    curCol = parseInt($(this).attr('curcol'));
    
                    sameColor = getBlocksWithSameColor(curRow, curCol);
                    if (sameColor.length > 1) {
                        over = false;
                    }
                }
            });
    
            return over;
        }
    });
    

    如果你对上述代码感兴趣,也可以到 http://download.csdn.net/detail/haitaohe/6702475处下载。

  • 相关阅读:
    UI层复习笔记
    async 的三大返回类型
    用scikit-learn进行LDA降维
    关于解决python线上问题的几种有效技术
    ASP.NET Core MVC/WebAPi 模型绑定探索
    浅谈 Fragment 生命周期
    vue2.0实践的一些细节
    Linux----------Mysql死锁
    Linux----------容器docker file
    Linux----------常用容器命令
  • 原文地址:https://www.cnblogs.com/riasky/p/3471579.html
Copyright © 2011-2022 走看看