(九)项目三日志 三

(九)项目三日志 二

Github:https://github.com/kevin-lh/SoftwarePractice/tree/main/Map


一、详细设计

1.1迷宫生成

请见上文哦

1.2 自动寻路

自动寻路应用A*算法实现,这里最后实在无法自行实现,有参考其他的代码

//寻找路径(astar算法)-地图、起点、终点
function findway(points, start, end) {
    var opens = [];  // 存放可检索的方块(开启列表)
    var closes = [];  // 存放已检索的方块(关闭列表)
    var cur = null;  // 当前指针
    var bFind = true;  // 是否检索  
    // 设置开始点的F、G为0并放入opens列表(F=G+H)
    start.F = 0;
    start.G = 0;
    start.H = 0;   
    // 将起点压入closes数组,并设置cur指向起始点
    closes.push(start);
    cur = start;    
    // 如果起始点紧邻结束点则不计算路径直接将起始点和结束点压入closes数组
    if (Math.abs(start.row - end.row) + Math.abs(start.col - end.col) == 1) {
        end.P = start;
        closes.push(end);
        bFind = false;
    }    
    // 计算路径
    while (cur && bFind) {
        //如果当前元素cur不在closes列表中,则将其压入closes列表中
        if (!inList(closes, cur)) 
            closes.push(cur);
        // 然后获取当前点四周点
        var rounds = getRounds(points, cur);
        // 当四周点不在opens数组中并且可移动,设置G、H、F和父级P,并压入opens数组
        for (var i = 0; i < rounds.length; i++) {
            if (rounds[i].val == 1 || inList(closes, rounds[i]) || inList(opens, rounds[i])) 
                continue;
            else if (!inList(opens, rounds[i]) && rounds[i].val != 1) {
                rounds[i].G = cur.G + 1;//不算斜的,只算横竖,设每格距离为1
                rounds[i].H = Math.abs(rounds[i].col - end.col) + Math.abs(rounds[i].row - end.row);
                rounds[i].F = rounds[i].G + rounds[i].H;
                rounds[i].P = cur;//cur为.P的父指针                
                opens.push(rounds[i]);
            }
        }        
        // 如果获取完四周点后opens列表为空,则代表无路可走,此时退出循环
        if (!opens.length) {
            cur = null;
            opens = [];
            closes = [];
            break;
        }        
        // 按照F值由小到大将opens数组排序
        opens.sort(function (a, b) {
            return a.F - b.F;
        });        
        // 取出opens数组中F值最小的元素,即opens数组中的第一个元素
        var oMinF = opens[0];
        var aMinF = [];  // 存放opens数组中F值最小的元素集合        
        // 循环opens数组,查找F值和cur的F值一样的元素,并压入aMinF数组。即找出和最小F值相同的元素有多少
        for (var i = 0; i < opens.length; i++) {
            if (opens[i].F == oMinF.F) 
                aMinF.push(opens[i]);
        }        
        // 如果最小F值有多个元素
        if (aMinF.length > 1) {
            // 计算元素与cur的曼哈顿距离
            for (var i = 0; i < aMinF.length; i++) {
                aMinF[i].D = Math.abs(aMinF[i].row - cur.row) + Math.abs(aMinF[i].col - cur.col);
            }           
            // 将aMinF按照D曼哈顿距离由小到大排序(按照数值的大小对数字进行排序)
            aMinF.sort(function (a, b) {
                return a.D - b.D;
            });                        
            oMinF = aMinF[0];
        }
        // 将cur指向D值最小的元素
        cur = oMinF;        
        // 将cur压入closes数组
        if (!inList(closes, cur)) 
            closes.push(cur);       
        // 将cur从opens数组中删除
        for (var i = 0; i < opens.length; i++) {
            if (opens[i] == cur) {
                opens.splice(i, 1);//将第i个值删除
                break;
            }
        }
        // 找到最后一点,并将结束点压入closes数组
        if (cur.H == 1) {
            end.P = cur;
            closes.push(end);
            cur = null;
        }
    }
    if (closes.length) {
        // 从结尾开始往前找
        var dotCur = closes[closes.length - 1];
        var path = [];  // 存放最终路径
        var i=0;
        while (dotCur) {
            path.unshift(dotCur);  // 将当前点压入path数组的头部
            dotCur = dotCur.P;  // 设置当前点指向父级            
            if (!dotCur.P) {
                dotCur = null;
            }
        }        
        return path;
    } 
    else {
        return false;
    }
}

1.3 手动控制

功能实现函数为drawnew,代码如下:

//手动控制
Maze.prototype.drawNew = function(){
    // for(let i =0 , len = this.mazeDataArray.length;i<len;i++){
    //     for(let j = 0,len = this.mazeDataArray[i].length ;j<len;j++){
            if(this.mazeDataArray[this.a][this.b].value){
                this.count++
                let tr = document.getElementsByTagName("tr");
                let td = tr[this.a].getElementsByTagName("td");
                let cell = td[this.b];
                console.log("走了");
                cell.setAttribute("class", "path");
                document.getElementById("count").innerHTML = this.count;
            } else {
                alert("撞墙啦!");
            }

            if(this.a===15&&this.b===15){
                alert("找到出口啦!");
            }
};

在此基础上,需增加键盘控制函数move,根据键码改变方向:

Maze.prototype.move = function(){
    //键盘事件
    window.addEventListener('keydown', (...args) => {
        let kc = args[0].keyCode;//获取键码
        //改变direction的值
        switch (kc) {
            case 38:
                this.a=this.a-1;
                console.log("上"+"["+this.a+","+this.b+"]");
                this.drawNew();
                break;
            case 39:
                this.b=this.b+1;
                console.log("右"+"["+this.a+","+this.b+"]");
                this.drawNew();
                break;
            case 40:
                this.a= this.a+1;
                console.log("下"+"["+this.a+","+this.b+"]");
                this.drawNew();
                break;
            case 37:
                this.b=this.b-1;
                console.log("左"+"["+this.a+","+this.b+"]");
                this.drawNew();
                break;
            default:
                //flag = false;
                break;
        }
    });
    //this.drawNew();
}

二、功能测试

为了便于演示效果,点击链接即可访问网页版
https://kevin-lh.github.io/Map/index.html
但还未做页面适配,所以与gui效果不一致请见谅!

2.1 自动寻路

(1)第一种map
在这里插入图片描述
(2)第二种map
在这里插入图片描述

2.2手动模式

在这里插入图片描述
遇到思路会有提示

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值