繁体   English   中英

单击jQuery选择器数组中的一项将应用于数组中的所有元素

[英]Click on 1 item in jQuery selector array is applying to all elements in the array

我正在尝试为扫雷游戏实现作弊功能,该游戏可显示1个随机的非炸弹正方形(第279行)以及其安全的相邻正方形(周围没有炸弹的8个正方形中的任何一个)。

但是由于某种原因,执行此$(this.nonBombCells.random()[0]).click()会触发所有非炸弹正方形显示(第260行),而不仅仅是随机的一个和安全的邻居直到遇到附近的炸弹。

如果我注释掉第279行并单击一个非炸弹单元,它会按预期工作。

我在这里有一个笨蛋: http ://plnkr.co/edit/OyC8LbFdsAFPn709pUiw?p=preview

我如何才能使此功能正常工作,就像人类单击该正方形一样?

相关代码:

(function($){

    // I am the controller for the mine sweeper game.
    function MineSweeper(selector, columnCount, rowCount, bombCount){
        var self = this;
        this.table = $(selector);
        this.columnCount = (columnCount || 30);
        this.rowCount = (rowCount || 30);

        // Check to see if the bomb count contains a percent sign.
        if ((typeof(bombCount) == "string") && (bombCount.indexOf("%") > 0)){
            // The bomb count is a percentage of the total number
            // of cells.
            this.bombCount = Math.floor(
                (this.columnCount * this.rowCount) *
                (parseInt(bombCount) / 100)
           );
        } else {
            // The bomb count is just a standard number.
            this.bombCount = (bombCount || 15);
        }

        // Bind the click handler for the table. This way, we
        // don't have to attach event handlers to each cell.
        this.table.click(
            function(event){
                // Pass off to the table click handler.
                self.onClick(event);
                // Cancel default event.
                return(false);
            }
       );

        // Initialize the table.
        this.initTable();
    };


    // I build the actual markup of the table using the
    // given number of columns and rows.
    MineSweeper.prototype.buildTable = function(){
        // Build the markup for a given row.
        var rowHtml = ("<tr>" + duplicateContent("<td class=\"active\">&nbsp;</td>", this.columnCount) + "</tr>");

        // Build the markup for the table using the row
        // data the given number of times.
        var tableHtml = duplicateContent(rowHtml, this.rowCount);

        // Set the HTML of the table to fill it out.
        this.table.html(tableHtml);
    };


    // I check to see if an end-game has been reached.
    // If so, then I give the option to restart.
    MineSweeper.prototype.checkEndGame = function(){
        var message = "";
        var isEndGame = false;

        // Check to see if any of the bombs have exploded.
        if (this.bombCells.filter(".bomb-revealed").size()){
            // Set the message.
            message = "You LOSE - Play Again?";
            // Flag the end game.
            isEndGame = true;
        // Check to see if there are any more active
        // non-bomb cells. If not, then the user has
        // successfully clicked all non-bomb cells.
        } else if (!this.nonBombCells.filter(".active").size()){
            // Set the message.
            message = "You WIN - Play Again?";
            // Flag the end game.
            isEndGame = true;
        }

        // Check to see if the game is over.
        if (isEndGame){
            // Prompt for replay.
            if (confirm(message)){
                // Restart the game.
                this.restart();
            }

        }
    };


    // I clear the table of any markup.
    MineSweeper.prototype.clearTable = function(){
        this.table.empty();
    };


    // I initialize the table.
    MineSweeper.prototype.initTable = function(){
        var self = this;
        // Clear the table if there is any existing markup.
        this.clearTable();

        // Now that we have ensured that the table is
        // empty, let's build out the HTML for the table.
        this.buildTable();

        // Gather the cells of the table.
        this.cells = this.table.find("td");
        // Set the "near bombs" data for each cell to
        // zero. This is the number of bombs that the cell
        // is near.
        this.cells.data("nearBombs", 0);

        // For each cell, keep a collection of the cells
        // that are near this cell.
        this.cells.each(function(index, cellNode){
            var cell = $(this);

            // Store the near cells.
            cell.data("near", cell.near());
        });

        // Randomly select and gather the bomb cells.
        this.bombCells = this.cells.randomFilter(this.bombCount).addClass("bomb");

        // Now that we've selected the bomb cells, let's
        // get teh non-bomb cells.
        this.nonBombCells = this.cells.filter(
            function(index){
                // If this cell does NOT appear in the bomb
                // cells collection, then it's a non-bomb
                // cell.
                return(self.bombCells.index(this) == -1);
            }
        );
        this.cheat();

        // Now that we have the bomb cells, let's go through
        // each of them and apply its "nearness" to the
        // cells around it.
        this.bombCells.each(
            function(index, node){
                var cell = $(this);
                var nearCells = cell.data("near");

                // For each near cell, increment the near
                // data counter.
                nearCells.each(function(){
                    var nearCell = $(this);

                    // Get the current near data and
                    // increment it.
                    nearCell.data("nearBombs", (nearCell.data("nearBombs") + 1));
                });
            }
        );
    };

    // I handle the clicks at the table level.
    MineSweeper.prototype.onClick = function(event){
        // Get the trigger for the event.
        var target = $(event.target);
        // Check to make sure the target is an active cell.
        // If it is not, then we are not interested.
        if (target.is("td.active")){ 
            // Check to see if the ALT key was pressed. If it
            // was, then we are handling the caution toggle.
            // If not, then we are going to process a normal
            // click event.
            if (event.altKey){

                // Toggle the caution nature of this cell.
                this.toggleCaution(target);

            } else {

                // Check to see if the target was a bomb cell.
                if (target.hasClass("bomb")){

                    // The user clicked on a bomb, which will end
                    // the game. Reveal the whole board (end-game
                    // check comes below).
                    this.revealBoard();

                } else {

                    // The target was not a bomb, so show it.
                    this.revealCell(target);

                }

                // Check end game.
                this.checkEndGame();

            }
        }


    };


    // I restart the game.
    MineSweeper.prototype.restart = function(){
        // Re-initialize the table.
        this.initTable();
    };


    // I reveal the entire board.
    MineSweeper.prototype.revealBoard = function(){
        // Remove the transient classes.
        this.cells.removeClass("active").removeClass("caution");

        // Add the bomb-revealed classes to the bombs.
        this.bombCells.addClass("bomb-revealed");

        // Set the cell contents.
        this.cells.each(
            function(index, cellNode){
                var cell = $(this);

                // Check to see if this is a bomb cell.
                if (cell.hasClass("bomb")){

                    // Show an *.
                    cell.html("*");

                } else if (cell.data("nearBombs")){

                    // Show the count.
                    cell.html(cell.data("nearBombs"));

                }
            }
       );
    };


    // I reveal the given cell.
    MineSweeper.prototype.revealCell = function(cell){
        var self = this;

        // Remove the active nature of the cell.
        cell.removeClass("active").removeClass("caution");
        // Check to see if the current cell is near any
        // bombs. If it is, then we'll just show the
        // current cell and it's nearness. If not, then
        // we'll continue to show the surrounding cells.
        if (cell.data("nearBombs")){
            // Set the content of the cell.
            cell.html(cell.data("nearBombs"));
        } else {
            // Make sure the cell has no markup.
            cell.html("");
            // This cell was not near any bombs. Therefore,
            // it is reasonable to assume the user would
            // quickly reveal all cells around it. As such,
            // we will do that for them.
            cell.data("near").filter(".active").each(
                function(index, cellNode){
                    if(!$(this).hasClass('bomb'))
                        self.revealCell($(this));
                }
           );
        }
    };

    // Toggle a cell with the caution symbol ("?")
    MineSweeper.prototype.toggleCaution = function(cell){
        if (cell.hasClass("caution")){
            cell.removeClass("caution");
            cell.html("&nbsp;");
        } else {
            cell.addClass("caution");
            cell.html("?");
        }
    }

    // Just don't have the patience? Me neither.
    MineSweeper.prototype.cheat = function() {
        var reveal = $(this.nonBombCells.random()[0]);
        reveal.click();
    }

    function duplicateContent(content, count){
        return new Array(count + 1).join(content);
    }

    $.fn.random = function() {
        return this.eq(Math.floor(Math.random() * this.length));
    }   

    // ------------------------------------------------------ //
    // ------------------------------------------------------ //


    // Store the mine sweeper class in the window scope so
    // that people can reach it ouside of this bubble.
    window.MineSweeper = MineSweeper;

})(jQuery);

如果您因为Plunker的问题而弹出“您赢了”的问题,则:

按ESC,这是因为279行(问题)导致它单击所有非炸弹单元,因此触发了获胜条件。

我只是将行260更改为$(this).revealCell(); 而且似乎运作良好。 不知道这是否正是您要的东西,但我认为是。

终于解决了问题。 当我使用this.cheatcell.data("nearBombs")始终为零。 所以我的猜测是您在附加数据之前调用this.cheat

所以我将this.cheat()移到了第155行,一切正常。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM