jQuery:太多的递归但是我需要为minesweeper递归

时间:2011-06-30 20:25:58

标签: javascript jquery

我对javascript相对较新。我正在尝试编写我的网络版扫雷。这是我需要的递归函数,它看起来工作正常,直到浏览器给出“太多的递归”错误。问题是我需要递归。有没有其他方法来编码扫雷?以下是演示:http://altynachar.com/minesweeper/

如果需要,我可以发布我的PHP代码。

function recursive(id){
                var id = id;
                //Determine what kind of cell this is: Clean, Bomb or Adjasent to bomb
                if($("#"+id).hasClass("adj")== true)
                    var under = "adj";
                if($("#"+id).hasClass("bomb")==true)
                    var under = "bomb";
                if($("#"+id).hasClass("clean")==true)
                    var under = "clean";

                //open up the cell          
                $("#"+id).hide();
                $("#under_"+id).show(); 

                //if it is bomb, open up whole grid and button for restart
                if(under == 'bomb')
                {       
                    $(".cover").hide();
                    $(".under").show();
                    $("body").append("<br /><input type='button' value='restart' onClick='javascript:window.location.reload();' />");
                } else {        

                    //if it is clean cell       
                    if(under == "clean")
                    {
                        //get all the adjasent cell ids
                        var split = id.split('-');
                        var row = parseInt(split[0]);
                        var col = parseInt(split[1]);
                        var adjasent = new Array();
                        adjasent[0] = (row-1)+"-"+ (col+1);
                        adjasent[1] =  row +"-"+(col+1);
                        adjasent[2] = (row+1)+"-"+(col+1);
                        adjasent[3] = (row+1)+"-"+col;
                        adjasent[4] = (row+1)+"-"+(col-1);
                        adjasent[5] =  row+"-"+(col-1);
                        adjasent[6] = (row -1)+"-"+(col-1);
                        adjasent[7] = (row -1)+"-"+col;

                        //loop through adjasent cells
                        for(var i=0; i<adjasent.length; i++)
                        {
                            var split2 = adjasent[i].split('-');
                            var row2 = parseInt(split2[0]);
                            var col2 = parseInt(split2[1]);

                            //check if cell is existent
                            if(row2 > 0 && row2 < 17)
                            {
                                if(col2 > 0 && col2 < 17)
                                {
                                    //perform recursion
                                    var adj = adjasent[i];
                                    recursive(adj);
                                } 
                            }                               
                        }
                    }
                } 
            }           

3 个答案:

答案 0 :(得分:2)

我的猜测是,如果你有两个相邻的干净单元格,你的代码将进行无限递归。

每次迭代都会递归到所有相邻的单元格。所以说单元格A和B彼此相邻,两者都很干净。 A将调用递归到B,然后递归到A,递归到B,依此类推。

您可以尝试清理递归,以便它不会查看已经看过的单元格,也可以删除递归。您可以通过向队列中添加任何看不见的干净单元格来完成相同的操作,并且只是一直弹出队列的末尾,直到它为空。这可能会更容易避免两次检查同一个单元格。


另外,不要仅仅为了将它们分成单独的数据而构建字符串。而不是:

adjasent[0] = (row-1)+"-"+ (col+1);
/* ... */
var split2 = adjasent[i].split('-');
var row2 = parseInt(split2[0]);
var col2 = parseInt(split2[1]);

只是做

adjacent[0] = { row: row-1, col: col+1 };
/* ... */
var row2 = adjacent[0].row
var col2 = adjacent[0].col

答案 1 :(得分:1)

您的递归本质上是深度优先搜索。问题是您没有考虑访问过的单元格。换句话说,假设你有2个细胞,A&amp; B:

A B

当您点击A时,它会搜索相邻的单元格,并会显示包含B的列表。你递归,然后寻找B的邻居,这是一个包含A的列表,然后你再次递归。这个循环永远不会结束。

您需要标记您访问的每个单元格,如果已经访问过,则需要返回:

function recursive(id){
    var id = id;

    if( $("#"+id).hasClass('visited') ) {
         return;
    }

    $("#"+id).addClass('visited');

    ...

}

然后你需要在递归完成后从所有内容中删除'visited':

$('div').removeClass('visited');

答案 2 :(得分:0)

保持一个正在运行的单元格ID数组,并在检查时从数组中删除这些值。

        var stack = ["first_id_to_check"];

        function check(id){
            var id = id;
            //Determine what kind of cell this is: Clean, Bomb or Adjasent to bomb
            if($("#"+id).hasClass("adj")== true)
                var under = "adj";
            if($("#"+id).hasClass("bomb")==true)
                var under = "bomb";
            if($("#"+id).hasClass("clean")==true)
                var under = "clean";

            //open up the cell          
            $("#"+id).hide();
            $("#under_"+id).show(); 

            //if it is bomb, open up whole grid and button for restart
            if(under == 'bomb')
            {       
                $(".cover").hide();
                $(".under").show();
                $("body").append("<br /><input type='button' value='restart' onClick='javascript:window.location.reload();' />");
            } else {        

                //if it is clean cell       
                if(under == "clean")
                {
                    //get all the adjasent cell ids
                    var split = id.split('-');
                    var row = parseInt(split[0]);
                    var col = parseInt(split[1]);
                    var adjasent = new Array();
                    adjasent[0] = (row-1)+"-"+ (col+1);
                    adjasent[1] =  row +"-"+(col+1);
                    adjasent[2] = (row+1)+"-"+(col+1);
                    adjasent[3] = (row+1)+"-"+col;
                    adjasent[4] = (row+1)+"-"+(col-1);
                    adjasent[5] =  row+"-"+(col-1);
                    adjasent[6] = (row -1)+"-"+(col-1);
                    adjasent[7] = (row -1)+"-"+col;

                    //loop through adjasent cells
                    for(var i=0; i<adjasent.length; i++)
                    {
                        var split2 = adjasent[i].split('-');
                        var row2 = parseInt(split2[0]);
                        var col2 = parseInt(split2[1]);

                        //check if cell is existent
                        if(row2 > 0 && row2 < 17)
                        {
                            if(col2 > 0 && col2 < 17)
                            {
                                stack.push(adjasent[i]);
                            } 
                        }                               
                    }
                }
            } 
        }

        while(stack[0]!==undefined) {
            check(stack[0]);
            stack.splice(0,1);
        }