寻路算法小游戏

news2025/1/23 22:42:55

 寻路算法小demo

寻路算法有两种,一种是dfs 深度优先算法,一种是

dfs 深度优先算法

深度优先搜索的步骤分为 1.递归下去 2.回溯上来。顾名思义,深度优先,则是以深度为准则,先一条路走到底,直到达到目标。这里称之为递归下去。

否则既没有达到目标又无路可走了,那么则退回到上一步的状态,走其他路。这便是回溯上来

 bfs 广度优先搜索

广度优先搜索较之深度优先搜索之不同在于,深度优先搜索旨在不管有多少条岔路,先一条路走到底,不成功就返回上一个路口然后就选择下一条岔路,而广度优先搜索旨在面临一个路口时,把所有的岔路口都记下来,然后选择其中一个进入,然后将它的分路情况记录下来,然后再返回来进入另外一个岔路,并重复这样的操作。

数据结构上的运用

DFS用递归的形式,用到了栈结构,先进后出。

BFS选取状态用队列的形式,先进先出。

<html>

<head>
    <title>寻路算法</title>
</head>

<body>
    <div class="body">
        <div class="body-content1">
            <div class="dfs-title">寻路算法</div>
            <div id="dfs-content" class="dfs-cell"></div>
            <div id="btn-list">
                <div id="btn-start-dfs" class="btn-start">dfs</div>
                <div id="btn-start-bfs" class="btn-start">bfs</div>
                <div id="btn-reset">重置</div>
            </div>
        </div>
        <div class="body-content2">
            <div class="dfs-title">.</div>
            <div class="start-point point">
                开始坐标:
                <input id="start-point-x" type="number" placeholder="行" />
                <input id="start-point-y" type="number" placeholder="列" />
            </div>
            <div class="target-point point">
                终点坐标:
                <input id="target-point-x" type="number" placeholder="行" />
                <input id="target-point-y" type="number" placeholder="列" />
            </div>
        </div>
    </div>
</body>
<script>
    let count = 0; //步数计数
    //迷宫地图
    let map = [
        [0, 0, 1, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 1, 0, 0, 0],
        [1, 0, 0, 0, 0, 1, 0, 0],
        [0, 0, 0, 0, 1, 0, 1, 0],
        [1, 0, 0, 0, 1, 0, 0, 0],
        [0, 0, 1, 0, 1, 0, 0, 0],
        [0, 1, 0, 0, 1, 1, 0, 1],
        [0, 0, 1, 1, 1, 0, 0, 0],
        [0, 0, 1, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 1, 0, 0, 0],
        [1, 0, 0, 0, 0, 1, 0, 0],
        [0, 0, 0, 0, 1, 0, 1, 0],
        [1, 0, 0, 0, 1, 0, 0, 0],
        [0, 0, 1, 0, 1, 0, 0, 0],
        [0, 1, 0, 0, 1, 1, 0, 1],
        [0, 0, 1, 1, 1, 0, 0, 0],
    ];
    let cellSize = 20; //px单元格大小
    let startX = 0, //开始坐标
        startY = 0;
    let targetX = 15, //结束坐标
        targetY = 7;
    let canFind = false;

    //遍历方向
    let dx = [0, 1, 0, -1],
        dy = [1, 0, -1, 0];

    let flag = new Array(map.length); //dfs标记走过的路径
    for (let i = 0; i < flag.length; i++) {
        flag[i] = new Array(map[i].length).fill(false);
    }
    //能否到达
    let findFlag = false;

    let step = new Array(map.length); //bfs标记走过的路径
    for (let i = 0; i < step.length; i++) {
        step[i] = new Array(map[i].length).fill(Infinity);
    }
    //单元格点击事件
    function cellClick(e) {
        let wFlag = 0;
        let classList = [...e.classList];
        if (classList.includes("now-in")) return;
        if (classList.includes("wall")) {
            e.classList.remove("wall");
            e.classList.add("space");
        } else if (classList.includes("space")) {
            e.classList.remove("space");
            e.classList.add("wall");
            wFlag = 1;
        }
        let id = e.id.split("-");
        let x = id[2],
            y = id[3];
        map[x][y] = wFlag;
        // console.log(map[x][y], x, y);
    }
    //初始化页面
    function init() {
        initPage();
        initData();
    }

    function initData() {
        const startPointX = document.getElementById("start-point-x");
        const startPointY = document.getElementById("start-point-y");
        const targetPointX = document.getElementById("target-point-x");
        const targetPointY = document.getElementById("target-point-y");
        startPointX.value = startX;
        startPointY.value = startY;
        targetPointX.value = targetX;
        targetPointY.value = targetY;

        startPointX.addEventListener("change", (e) => {
            if (
                e.target.value < 0 ||
                e.target.value >= map.length ||
                map[e.target.value][startY] == 1
            ) {
                alert("非法坐标,请重新输入");
                startPointX.value = startX;
                return;
            }
            startX = parseInt(e.target.value);
            initPage();
        });
        startPointY.addEventListener("change", (e) => {
            if (
                e.target.value < 0 ||
                e.target.value >= map[0].length ||
                map[startX][e.target.value] == 1
            ) {
                alert("非法坐标,请重新输入");
                startPointY.value = startY;
                return;
            }
            startY = parseInt(e.target.value);
            initPage();
        });
        targetPointX.addEventListener("change", (e) => {
            if (
                e.target.value < 0 ||
                e.target.value >= map.length ||
                map[e.target.value][targetY] == 1
            ) {
                alert("非法坐标,请重新输入");
                targetPointX.value = targetX;
                return;
            }
            targetX = parseInt(e.target.value);
            initPage();
        });
        targetPointY.addEventListener("change", (e) => {
            if (
                e.target.value < 0 ||
                e.target.value >= map[0].length ||
                map[targetX][e.target.value] == 1
            ) {
                alert("非法坐标,请重新输入");
                targetPointY.value = targetY;
                return;
            }
            targetY = parseInt(e.target.value);
            initPage();
        });
    }

    function initPage() {
        let innerHtml = ``;
        count = 0;
        findFlag = false;
        for (let i = 0; i < map.length; i++) {
            for (let j = 0; j < map[i].length; j++) {
                flag[i][j] = false;
                innerHtml += `<div id="${"dfs-id-" + i + "-" + j}" class="${
            map[i][j] == 0 ? "space" : "wall"
          } cell" style="width:${cellSize}px;height:${cellSize}px;" click="cellClick"></div>`;
            }
        }
        let dfsContent = document.getElementById("dfs-content");
        dfsContent.style.width = map[0].length * (cellSize + 2) + "px";
        dfsContent.innerHTML = innerHtml;

        let startCell = document.getElementById(
            "dfs-id-" + startX + "-" + startY
        );
        startCell.classList.add("now-in");

        let targetCell = document.getElementById(
            "dfs-id-" + targetX + "-" + targetY
        );
        targetCell.classList.add("target-in");
        let cell = document.getElementsByClassName("cell");
        for (let i = 0; i < cell.length; i++) {
            cell[i].addEventListener("click", () => {
                cellClick(cell[i]);
            });
        }
    }

    function dfs(x, y) {
        const dx = [1, 0, -1, 0],
            dy = [0, 1, 0, -1];
        if (x < 0 || y < 0 || x >= map.length || y >= map[0].length) return;
        if (map[x][y] == 1 || flag[x][y] || findFlag) return;
        let startCell = document.getElementById("dfs-id-" + x + "-" + y);
        startCell.classList.add("now-in");
        if (x == targetX && y == targetY) {
            findFlag = true;
            startCell.innerHTML = `<div style="font-size:small;text-align: center;">${count}</div>`;
            canFind = true;
            return;
        }
        for (let i = 0; i < 4 && !findFlag; i++) {
            flag[x][y] = true;
            startCell.innerHTML = `<div style="font-size:small;text-align: center;">${count}</div>`;
            count++;
            startCell.classList.add("pass");
            startCell.classList.remove("now-in");

            if (!findFlag) dfs(x + dx[i], y + dy[i]);
            if (!findFlag) flag[x][y] = false;
            if (!findFlag) startCell.innerHTML = "";
            if (!findFlag) count--;
            if (!findFlag) startCell.classList.remove("pass");
        }
    }

    function bfs() {
        let quene = [
            [startX, startY]
        ];
        step[startX][startY] = 0;
        // console.log("开始bfs");
        let res = [];
        flag[startX][startY] = true;
        while (quene.length) {
            let p = quene.shift();
            res.push(p);
            let x = p[0],
                y = p[1];
            if (x == targetX && y == targetY) break;
            let f = false;
            for (let i = 0; i < 4; i++) {
                let nx = x + dx[i],
                    ny = y + dy[i];
                if (nx < 0 || nx >= map.length || ny >= map[0].length || ny < 0) {
                    continue;
                }
                if (map[nx][ny] == 1 || flag[nx][ny] == true) {
                    continue;
                }
                flag[nx][ny] = true;
                step[nx][ny] = step[x][y] + 1;
                quene.push([nx, ny]);
                if (nx == targetX && ny == targetY) {
                    f = true;
                    canFind = true;
                    break;
                }
            }
            if (f) break;
        }
        if (canFind) bfsDrawRoad();
    }
    //绘制路线
    function bfsDrawRoad() {
        let road = [
            [targetX, targetY]
        ];
        while (road[0][0] != startX || road[0][1] != startY) {
            let x = road[0][0],
                y = road[0][1];
            for (let i = 0; i < 4; i++) {
                let nx = x + dx[i],
                    ny = y + dy[i];
                if (nx < 0 || ny < 0 || nx >= step.length || ny >= step[0].length)
                    continue;
                if (step[x][y] == step[nx][ny] + 1) {
                    road.unshift([nx, ny]);
                    break;
                }
            }
        }
        for (let i = 0; i < road.length; i++) {
            let startCell = document.getElementById(
                "dfs-id-" + road[i][0] + "-" + road[i][1]
            );
            if (i != road.length - 1) {
                startCell.classList.add("pass");
            } else {
                startCell.classList.add("now-in");
            }

            startCell.innerHTML = `<div style="font-size:small;text-align: center;">${i}</div>`;
        }
    }
    //页面初始化
    init();
    //开始dfs
    let startBtnDfs = document.getElementById("btn-start-dfs");
    startBtnDfs.addEventListener("click", () => {
        canFind = false;
        init();
        dfs(startX, startY);
        // console.log(canFind);
        if (!canFind) alert("无法达到");
    });
    //开始bfs
    let startBtnBfs = document.getElementById("btn-start-bfs");
    startBtnBfs.addEventListener("click", () => {
        canFind = false;
        init();
        bfs();
        // console.log(canFind);
        if (!canFind) alert("无法达到");
    });
    //重置页面
    let resetBtn = document.getElementById("btn-reset");
    resetBtn.addEventListener("click", () => {
        init();
    });
</script>
<style>
    .body {
        display: flex;
        margin: auto;
    }
    
    .body-content1 {
        flex: 1;
    }
    
    .body-content2 {
        flex: 1;
    }
    
    .point {
        margin-top: 1rem;
    }
    
    .dfs-cell {
        display: flex;
        flex-wrap: wrap;
        margin: auto;
    }
    
    .dfs-cell>.cell {
        border: 1px solid gray;
        cursor: pointer;
    }
    
    .dfs-cell>.wall {
        background-color: black;
    }
    
    .now-in {
        background-color: yellow;
    }
    
    .target-in {
        background-color: rgb(245, 162, 9);
    }
    
    .pass {
        background-color: yellowgreen;
    }
    
    .dfs-title {
        text-align: center;
        margin: 2rem;
    }
    
    #btn-list {
        display: flex;
        justify-content: space-between;
        width: 20rem;
        margin: auto;
    }
    
    .btn-start {
        padding: 1rem;
        margin: auto;
        margin-top: 2rem;
        text-align: center;
        background-color: violet;
        width: 2rem;
        cursor: pointer;
    }
    
    #btn-reset {
        padding: 1rem;
        margin: auto;
        margin-top: 2rem;
        text-align: center;
        background-color: violet;
        width: 2rem;
        cursor: pointer;
    }
</style>

</html>

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/894879.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

spring的核心技术---bean的生命周期加案例分析详细易懂

目录 一.spring管理JavaBean的初始化过程&#xff08;生命周期&#xff09; Spring Bean的生命周期&#xff1a; 二.spring的JavaBean管理中单例模式及原型&#xff08;多例&#xff09;模式 2.1 . 默认为单例&#xff0c;但是可以配置多例 2.2.举例论证 2.2.1 默认单例 2.2…

什么是报表测试?报表测试有哪些?

报表测试主要分为&#xff1a;报表界面测试、报表安全性、报表准确性、报表展示速度&#xff08;也就是性能&#xff09;。 数据准确性测试 报表测试的系统分为两类&#xff0c;一类是业务系统中&#xff0c;带有统计分析功能模块&#xff0c;该模块中包含分析报表&#xff0c;…

Docker碎碎念

docker和虚拟机的区别 虚拟机&#xff08;VM&#xff09;是通过在物理硬件上运行一个完整的操作系统来实现的。 每个虚拟机都有自己的内核、设备驱动程序和用户空间&#xff0c;它们是相互独立且完全隔离的。 虚拟机可以在不同的物理服务器之间迁移&#xff0c;因为它们是以整…

【仿写tomcat】六、解析xml文件配置端口、线程池核心参数

线程池改造 上一篇文章中我们用了Excutors创建了线程&#xff0c;这里我们将它改造成包含所有线程池核心参数的形式。 package com.tomcatServer.http;import java.util.concurrent.*;/*** 线程池跑龙套** author ez4sterben* date 2023/08/05*/ public class ThreadPool {pr…

社科院与美国杜兰大学金融管理硕士项目——畅游于金融世界

随着社会经济的不断发展&#xff0c;职场竞争愈发激烈&#xff0c;很多同学都打算通过报考研究生来实现深造&#xff0c;提升自己的综合能力和竞争优势&#xff0c;获得优质的证书。而对于金融专业的学生和在职人员来说&#xff0c;社科院与美国杜兰大学金融管理硕士项目是一个…

ElasticSearch7.x + kibana7.x使用记录

目录 查询所有索引 查询索引的mapping信息 添加索引的同时添加mapping 在原有基础上新增字段 旧的索引迁移到新的索引&#xff08;使用场景&#xff1a;数据迁移、索引优化、数据转换&#xff09; 查询索引下的文档总数 场景1&#xff1a;某一个字段的值是数组&#xff0…

数据的深海潜行:数据湖、数据仓库与数据湖库之间的微妙关系

导言&#xff1a;数据的重要性与存储挑战 在这个信息爆炸的时代&#xff0c;数据已经成为企业的核心资产&#xff0c;而如何高效、安全、便捷地存储这些数据&#xff0c;更是每个组织面临的重大挑战。 数据作为组织的核心资产 数据在过去的几十年里从一个辅助工具演变成企业的…

视频怎么转换成gif表情包?三步完成视频在线转gif

小伙伴们在使用gif表情包的时候&#xff0c;都会注意到有些是视频片段&#xff0c;其实视频转换成gif动图已经很常见了&#xff0c;今天就来给大家演示一下使用视频转gif工具&#xff08;https://www.gif.cn&#xff09;来将视频在线转gif&#xff0c;一起来学习一下吧。 打开…

ps由于找不到msvcp140.dll无法继续执行需要怎么处理

最近在使用Photoshop时遇到了一个问题&#xff0c;它提示我缺少了msvcp140.dll文件。这让我无法正常使用Photoshop&#xff0c;非常困扰。然而&#xff0c;通过一番尝试和研究&#xff0c;我终于成功修复了这个问题&#xff0c;小编就把修复方法分享给大家。 ps为什么会由于找不…

【文生图系列】Denoising Diffusion Probabilistic Models论文解读

文章目录 扩散模型扩散过程反向过程优化目标 训练过程参考 此篇论文是DDPM的奠基之作&#xff0c;后续扩散模型相关论文都基本继承了前向加噪-反向降噪-训练这样的框架。论文全是公式&#xff0c;理解起来好难好难。 【文生图系列】基础篇-马尔可夫链 【文生图系列】基础篇-变分…

springboot中的properties配置文件:MySQL密码添加双引号会报错

在springboot项目中&#xff0c;如果使用的配置文件是properties 格式&#xff0c;那么给属性的值添加双引号可能会出错&#xff0c;比如给MySQL的密码添加双引号&#xff1a; 我们在调试模式下&#xff0c;一探究竟&#xff1a; 然后在其poolProperties中查看&#xff0c;密…

如何快速在vscode中实现不同python文件的对比查看

总体而言&#xff1a;两种方式。一种是直接点击vscode右上角的图标&#xff08;见下图&#xff09;。 另一种方式就是使用快捷键啦“**Ctrl**”&#xff0c;用的时候选中想要对比的python文件&#xff0c;然后快捷键就可以达到下图效果了&#xff1a; 建议大家直接使用第二种…

Java课题笔记~ SpringBoot基础配置

二、基础配置 1. 配置文件格式 问题导入 框架常见的配置文件有哪几种形式&#xff1f; 1.1 修改服务器端口 http://localhost:8080/books/1 >>> http://localhost/books/1 SpringBoot提供了多种属性配置方式 application.properties server.port80 applicati…

电动汽车太秀了!用一个技巧搞定了蓄电池!

当涉及能源存储和供应&#xff0c;特别是在太阳能、电动车和不间断电源等领域&#xff0c;蓄电池无疑是关键的组成部分。然而&#xff0c;蓄电池的状态、性能和健康状况对于系统的可靠性和效率至关重要。 蓄电池监控通过实时监测、数据分析和预警功能&#xff0c;它提供了更高效…

PCB老化测试注意事项和操作流程

PCB老化测试是为了评估PCB在实际应用环境中的可靠性和寿命而进行的测试。以下是PCB老化测试的一般步骤和一些注意事项&#xff1a; 步骤&#xff1a; 1. 确定老化条件&#xff1a;根据实际应用环境和需求&#xff0c;确定老化测试的条件&#xff0c;如温度、湿度、电压等。这些…

基于Redis实现关注、取关、共同关注及消息推送(含源码)

微信公众号访问地址&#xff1a;基于Redis实现关注、取关、共同关注及消息推送(含源码) 推荐文章&#xff1a; 1、springBoot对接kafka,批量、并发、异步获取消息,并动态、批量插入库表; 2、SpringBoot用线程池ThreadPoolTaskExecutor异步处理百万级数据; 3、为什么引入Rediss…

【3Ds Max】可编辑多边形“点”层级的简单使用

目录 简介 示例 &#xff08;1&#xff09;移除 &#xff08;2&#xff09;断开 &#xff08;3&#xff09;焊接 &#xff08;4&#xff09;挤出 &#xff08;5&#xff09;切角 &#xff08;6&#xff09;目标焊接 &#xff08;7&#xff09;连接 简介 在3ds Max中&…

Golang使用MinIO

最近在使用Golang做了一个网盘项目&#xff08;学习&#xff09;&#xff0c;文件存储一直保存在本地&#xff08;各厂商提供的oss贵&#xff09;&#xff0c;所以就在思考怎么来处理这些文件&#xff0c;类似的方案很对hdfs、fastdfs&#xff0c;但这其中MinIO是最近几年比较火…

网安周报|Monti Ransomware团伙推出了一个新的Linux加密器

Monti Ransomware团伙推出了一个新的Linux加密器 经过两个月的休息&#xff0c;Monti 勒索软件运营商带着新的 Linux 版本的加密器返回。该变体被用于针对政府和法律部门组织的攻击。研究人员注意到两个团伙的TTP之间有多个相似之处&#xff0c;Monti运营商还基于Conti泄露的源…