js实现广度优先搜索和深度优先搜索

最近在学习算法,看了图解算法,但是感觉写的太简单,理论比较多,代码实现比较和例子比较少,看完后,又接着看了《啊哈!算法》,这个感觉例子比较多,也比较适合我这种算法入门的读者。

书上的例子一一打了一遍,因为作者是用c写的,而我是没接触过c,用了自己比较熟悉的js把例子打了一遍。用广搜写了贪吃蛇自动吃果实,只能吃100多个,自认为还能完善,于是等完善后在放在博客上面吧。

这里先写写用dfs(深搜) 和 bfs(广搜)算法实现 炸弹人的统计哪个点能消灭的怪物最多的算法

这里是地图,要求从3,3位置走,在那个地方消灭的怪物最多

在这里插入图片描述

这里是用bfs 完成目标的算法 ,基本上都有注释

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>炸弹人</title>
</head>
<body>
<script>
    function note(x,y){
        this.x = x;
        this.y = y;
    }
    var a = [
                ["#","#","#","#","#","#","#","#","#","#","#","#","#"],//1
                ["#","G","G",".","G","G","G","#","G","G","G",".","#"],//2
                ["#","#","#",".","#","G","#","G","#","G","#","G","#"],//3
                ["#",".",".",".",".",".",".",".","#",".",".","G","#"],//4
                ["#","G","#",".","#","#","#",".","#","G","#","G","#"],//5
                ["#","G","G",".","G","G","G",".","#",".","G","G","#"],//6
                ["#","G","#",".","#","G","#",".","#",".","#",".","#"],//7
                ["#","#","G",".",".",".","G",".",".",".",".",".","#"],//8
                ["#","G","#",".","#","G","#","#","#",".","#","G","#"],//9
                ["#",".",".",".","G","#","G","G","G",".","G","G","#"],//10
                ["#","G","#",".","#","G","#","G","#",".","#","G","#"],//11
                ["#","G","G",".","G","G","G","#","G",".","G","G","#"],//12
                ["#","#","#","#","#","#","#","#","#","#","#","#","#"]//13

            ];


    //计算当前点能炸多少个怪物
    function getnum(i,j){

        var sum, x,y;
        sum = 0;//sum用来计数(可以消灭的敌人数),所以需要初始化为0
        //将坐标i,j复制到两个新变量中,以便之后向上下左右四个方向统计可以被消灭的敌人的数目
        //向上统计可以消灭的敌人的数目
        x = i;
        y = j;
        while(a[x][y]!="#"){//判断的点是不是墙,如果不是墙就继续
            if(a[x][y]=="G"){
                sum++;
            }
                //x--的作用是继续向上统计
                x--;


        }

        //向下统计可以消灭的敌人数
        x = i;
        y = j;
        while(a[x][y]!="#"){
            if(a[x][y]=="G")
            {
                sum++;
            }
                //x++向下统计
                x++;

                    }

        //向左统计可以消灭的敌人数
        x = i;
        y = j;
        while(a[x][y]!="#"){
            if(a[x][y]=="G")
            {
                sum++;
            }
                //x++向下统计
                y--;

        }

        //向右统计可以消灭的敌人数
        x = i;
        y = j;
        while(a[x][y]!="#"){
            if(a[x][y]=="G")
            {
                sum++;
            }
                //x++向下统计
                y++;

        }

        return sum;
    }

    var que = [];
    //假设地图大小不超过20*20,因此队列扩展不超过400个
    var head,tail;
    var book = [];
    //初始化标记数组 为0;
    for(var i = 1;i<=20;i++ ){
        var now = [];
        for(var j = 1;j<=20;j++){
            now[j] = 0;
        }
        book[i] = now;
    }
    var i, j, k,sum,max= 0,mx,my, n, m,startx,starty,tx,ty;

    //定义一个用于表示走的方向的数组  数组和坐标的表现方法正好相反
    var next = [[0,1],//向右走
                [1,0],//向下走
                [0,-1],//向左走
                [-1,0]];//向上走

    //表示有多少行字符,m表示有多少列字符
    n = 13;
    m = 13;
    //给小人的坐标赋值
    startx = 3;
    starty = 3;
    //队列初始化
    head = 1;
    tail = 1;
    //向初始队列中插入小人的坐标
    que[tail] = new  note();
    que[tail].x = startx;
    que[tail].y = starty;
    //保证初始的tail比head大于,也就是head是tail队列的上一个元素
    tail++;
    //开始点设置为1
    book[startx][starty]=1;

    //先把初始点的数量赋值给max
    max = getnum(startx,starty);
    mx = startx;
    my = starty;

    //接下来便是扩展,也就是深度优先搜索的核心
    //当队列不为空时循环
    while(head<tail){
        //枚举四个方向
        for(k=0;k<=3;k++){
            //尝试走下一个点
            tx = que[head].x + next[k][0];
            ty = que[head].y + next[k][1];
            //判断是否越界
            if(tx<0||tx>n-1||ty<0||ty>m-1){
                continue;
            }
            //判断是否为平地或者曾经走过的
            if(a[tx][ty]=="."&&book[tx][ty]==0){

                //每个点只入队一次,所以要标记这个点已经走过
                book[tx][ty]=1;
                //插入新扩展的点到队列中
                que[tail] = new  note();
                que[tail].x = tx;
                que[tail].y = ty;
                tail++;
                sum =getnum(tx,ty);
                if(sum>max){
                    //如果当前统计出的数目大于max,那么跟新max,并用mx,my记录该点的坐标
                    max = sum;
                    mx = tx;
                    my = ty;

                }

            }

        }
        head++;

    }

    console.log("坐标是:("+mx+","+my+")消灭的最大数量为:"+max);

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

这里是深搜实现的方法

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>炸弹人</title>
</head>
<body>
<script>
    function note(x,y){
        this.x = x;
        this.y = y;
    }
    var a = [
        ["#","#","#","#","#","#","#","#","#","#","#","#","#"],//1
        ["#","G","G",".","G","G","G","#","G","G","G",".","#"],//2
        ["#","#","#",".","#","G","#","G","#","G","#","G","#"],//3
        ["#",".",".",".",".",".",".",".","#",".",".","G","#"],//4
        ["#","G","#",".","#","#","#",".","#","G","#","G","#"],//5
        ["#","G","G",".","G","G","G",".","#",".","G","G","#"],//6
        ["#","G","#",".","#","G","#",".","#",".","#",".","#"],//7
        ["#","#","G",".",".",".","G",".",".",".",".",".","#"],//8
        ["#","G","#",".","#","G","#","#","#",".","#","G","#"],//9
        ["#",".",".",".","G","#","G","G","G",".","G","G","#"],//10
        ["#","G","#",".","#","G","#","G","#",".","#","G","#"],//11
        ["#","G","G",".","G","G","G","#","G",".","G","G","#"],//12
        ["#","#","#","#","#","#","#","#","#","#","#","#","#"]//13

    ];

    //计算当前点能炸多少个怪物
    function getnum(i,j){

        var sum, x,y;
        sum = 0;//sum用来计数(可以消灭的敌人数),所以需要初始化为0
        //将坐标i,j复制到两个新变量中,以便之后向上下左右四个方向统计可以被消灭的敌人的数目
        //向上统计可以消灭的敌人的数目
        x = i;
        y = j;
        while(a[x][y]!="#"){//判断的点是不是墙,如果不是墙就继续
            if(a[x][y]=="G"){
                sum++;
            }
            //x--的作用是继续向上统计
            x--;


        }

        //向下统计可以消灭的敌人数
        x = i;
        y = j;
        while(a[x][y]!="#"){
            if(a[x][y]=="G")
            {
                sum++;
            }
            //x++向下统计
            x++;

        }

        //向左统计可以消灭的敌人数
        x = i;
        y = j;
        while(a[x][y]!="#"){
            if(a[x][y]=="G")
            {
                sum++;
            }
            //x++向下统计
            y--;

        }

        //向右统计可以消灭的敌人数
        x = i;
        y = j;
        while(a[x][y]!="#"){
            if(a[x][y]=="G")
            {
                sum++;
            }
            //x++向下统计
            y++;

        }

        return sum;
    }

    function dfs(x,y){
        var next = [[0,1],//向右走
            [1,0],//向下走
            [0,-1],//向左走
            [-1,0]];//向上走

        var k,sum,tx,ty;
        //计算当前点所消灭的敌人
        sum = getnum(x,y);
        //更新max的值和坐标
        if(sum>max){
            max = sum;
            mx = x;
            my = y;
        }
        //枚举四个方向
        for(k = 0;k<=3;k++){
            //下一个点的坐标
            tx = x + next[k][0];
            ty = y + next[k][1];
            //判断是否出局
            if(tx<0||tx>n-1||ty<0||ty>m-1){
                continue;
            }
            //判断是否可走 并且没有被标记过
            if(a[tx][ty]=="."&&book[tx][ty]==0){
                //更新标记
                book[tx][ty] = 1;
                //开始尝试走下一个点
                dfs(tx,ty);
            }
        }
        //返回到上一个方法
        return;
    }
    var i,startx,starty,max,mx,my;
    //初始化记录队列
    var book = [];
    //初始化标记数组 为0;
    for(var i = 1;i<=20;i++ ){
        var now = [];
        for(var j = 1;j<=20;j++){
            now[j] = 0;
        }
        book[i] = now;
    }

    //表示有多少行字符,m表示有多少列字符
    n = 13;
    m = 13;
    //给小人的坐标赋值
    startx = 3;
    starty = 3;

    //开始点设置为1
    book[startx][starty]=1;

    //先把初始点的数量赋值给max
    max = getnum(startx,starty);
    mx = startx;
    my = starty;

    dfs(startx,starty);

    console.log("坐标是:("+mx+","+my+")消灭的最大数量为:"+max);
</script>
</body>
</html>

答案应该是下面的

在这里插入图片描述

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值