简单四方向a*寻路学习记录7 实现了多个障碍绕行但是绕路

go 复制代码
import { _decorator, Collider2D, Component, Contact2DType, director, IPhysics2DContact, Node } from 'cc';
const { ccclass, property,executeInEditMode } = _decorator;

@ccclass('xiaobingduozhangai')




@executeInEditMode
export class xiaobingduozhangai extends Component {
    juesex:number=null;
    juesey:number=null;
    mubiaox:number=null;
    mubiaoy:number=null;
    shangf:number=0;
    shangg:number=0;

    shangh:number=0;


    zuof:number=0;
    zuoh:number=0;
    zuog:number=0;
    youf:number=0;
    youh:number=0;
    youg:number=0;
    xiaf:number=0;
    xiah:number=0;
    xiag:number=0;
    shangx:number=0;
    shangy:number=0;
    zuox:number=0;
    zuoy:number=0;
    youx:number=0;
    youy:number=0;
    xiax:number=0;
    xiay:number=0;
    zhangaix:number=0;
    zhangaiy:number=0;
    zhangaifangxiang:number=0;


    zuoguox:number=0;
    zuoguoy:number=0;
    neighbors: {x: number, y: number, f: number}[];
    zuoguo: {x: number, y: number}[];
    ditu:[][]=null;
    onLoad(){

        // 监听碰撞事件

      const collider = this.getComponent(Collider2D);
      
      if (collider) {
          collider.on(Contact2DType.BEGIN_CONTACT, this.onBeginContact, this);
          
          
      }
      director.on('gezi_ditu_xiaobing', this.huoquditu, this);
        

      
      
      
      
      
      
      
      
      
      
      
      
      
      
      

      this.neighbors=[];
      this.zuoguo=[];
    }

    
    // 碰撞回调
    onBeginContact(selfCollider: Collider2D, otherCollider: Collider2D, contact: IPhysics2DContact | null) {
        if(otherCollider.node.name.includes("shantou")){
            this.scheduleOnce(()=>{

                selfCollider.node.destroy();
            },0.7);
        }
    }
    start() {

        director.emit('xiaobing_position_gezi', this.node.worldPosition);
    }

    update(deltaTime: number) {

    }








    huoquditu(ditu:[][]){
        this.ditu=ditu;
       let len=ditu.length;
       console.log(len+"=");

       for(let y=0;y<len;y++){
        for(let x=0;x<ditu[y].length;x++){
            console.log(ditu[y][x]);
            if(ditu[y][x]==1){
                this.mubiaox=x;

                this.mubiaoy=y;

                console.log("/"+this.mubiaox,this.mubiaoy)
            }else if(ditu[y][x]==7){
                this.juesex=x;
                this.juesey=y;
                console.log("/"+this.juesex,this.juesey);
            }else if(ditu[y][x]==11){
                this.zhangaix=x;
                this.zhangaiy=y;
            }
            
        }
           
       }
       //this.jisuanf(this.juesex,this.juesey);
       this.huoqushangxiazuoyou(this.juesex,this.juesey,0);
    }

    jisuannext(x:number,y:number,f:number,g:number){
        
        
        if(f>0){

            //g=g+1;
            this.huoqushangxiazuoyou(x,y,(g+1));
        }


    }

    panduanzhangai(x:number,y:number):boolean{


        if(x>=10||x<0||y>=10||y<0){
            return true
        }
        if(this.ditu[y][x]==11){
            return true;
        }







        return false;


    }
// 添加一个辅助方法
isAlreadyVisited(x: number, y: number): boolean {
    return this.zuoguo.some(point => point.x === x && point.y === y);
}
    huoqushangxiazuoyou(qidianx:number,qidiany:number,g:number){
        










         // 安全阀
    if(g > 200) {
        console.log("❌ 安全阀激活:已走200步,停止递归");
        return;
    }
    
    // 1. 先记录当前点已经访问过
    this.zuoguo.push({x: qidianx, y: qidiany});
    console.log(`🔵 记录起始点 [${qidianx},${qidiany}] 到已访问列表`+"现在是第"+g);
    
    // 2. 计算四个方向的基础值
    const ng = g + 1;
    
    const directions = [
        { 
            name: '上', x: qidianx, y: qidiany - 1, 
            g: ng, h: 0, f: 0, isValid: true 
        },
        { 
            name: '下', x: qidianx, y: qidiany + 1, 
            g: ng, h: 0, f: 0, isValid: true 
        },
        { 
            name: '左', x: qidianx - 1, y: qidiany, 
            g: ng, h: 0, f: 0, isValid: true 
        },
        { 
            name: '右', x: qidianx + 1, y: qidiany, 
            g: ng, h: 0, f: 0, isValid: true 
        }
    ];
    
    // 3. 为每个方向计算h值和f值,并检查有效性
    let validDirections = [];
    for (let dir of directions) {
        // 计算启发值(Manhattan距离)
        dir.h = Math.abs(dir.x - this.mubiaox) + Math.abs(dir.y - this.mubiaoy);
        
        // 边界惩罚
        if (dir.name === '右' && dir.x >= 9) {
            dir.h += 1;
            console.log(`⚠️ 边界惩罚:右边方向 h+=1`);
        }
        
        dir.f = dir.g + dir.h;
        
        // 检查有效性:障碍物或已访问
        const isObstacle = this.panduanzhangai(dir.x, dir.y);
        const isVisited = this.isAlreadyVisited(dir.x, dir.y);
        
        if (isObstacle) {
            console.log(`❌ ${dir.name}方向 [${dir.x},${dir.y}] 是障碍物`);
            dir.isValid = false;
        } else if (isVisited) {
            console.log(`⏭️ ${dir.name}方向 [${dir.x},${dir.y}] 已访问过`);
            dir.isValid = false;
        } else {
            console.log(`✅ ${dir.name}方向 [${dir.x},${dir.y}] g=${dir.g}, h=${dir.h}, f=${dir.f}`);
            dir.isValid = true;
            // 添加到neighbors(开放列表)
            this.neighbors.push({x: dir.x, y: dir.y, f: dir.f});
            validDirections.push(dir);
        }
    }
    
    // 4. 如果没有有效的方向
    if (validDirections.length === 0) {
        console.log("🚫 没有有效的方向可走!");
        
        // 尝试从neighbors中找未访问的替代点
        let bestAlternative = null;
        let minF = Number.MAX_SAFE_INTEGER;
        
        for (let i = 0; i < this.neighbors.length; i++) {
            const neighbor = this.neighbors[i];
            const notVisited = !this.isAlreadyVisited(neighbor.x, neighbor.y);
            if (neighbor.f >= 0 && neighbor.f < minF && notVisited) {
                minF = neighbor.f;
                bestAlternative = neighbor;
            }
        }
        
        if (bestAlternative) {
            console.log(`🔄 从neighbors中选择替代点 [${bestAlternative.x},${bestAlternative.y}] f=${bestAlternative.f}`);
            // 这里是关键:继续递归这个替代点
            this.huoqushangxiazuoyou(bestAlternative.x, bestAlternative.y, g + 1);
        } else {
            console.log("💀 完全无路可走!");
        }
        return;
    }
    
    // 5. 从有效方向中选择f值最小的
    let bestDirection = validDirections[0];
    for (let i = 1; i < validDirections.length; i++) {
        if (validDirections[i].f < bestDirection.f) {
            bestDirection = validDirections[i];
        }
    }
    
    console.log(`📍 选择方向:${bestDirection.name} [${bestDirection.x},${bestDirection.y}] f=${bestDirection.f}`);
    
    // 6. 更新你的directionData(保持原来结构)
    this.shangx = directions[0].x;
    this.shangy = directions[0].y;
    this.shangf = directions[0].isValid ? directions[0].f : -1;
    this.shangg = directions[0].g;
    this.shangh = directions[0].h;
    
    this.xiax = directions[1].x;
    this.xiay = directions[1].y;
    this.xiaf = directions[1].isValid ? directions[1].f : -1;
    this.xiag = directions[1].g;
    this.xiah = directions[1].h;
    
    this.zuox = directions[2].x;
    this.zuoy = directions[2].y;
    this.zuof = directions[2].isValid ? directions[2].f : -1;
    this.zuog = directions[2].g;
    this.zuoh = directions[2].h;
    
    this.youx = directions[3].x;
    this.youy = directions[3].y;
    this.youf = directions[3].isValid ? directions[3].f : -1;
    this.youg = directions[3].g;
    this.youh = directions[3].h;
    
    const directionData = {
        shangf: this.shangf,
        xiaf: this.xiaf,
        zuof: this.zuof,
        youf: this.youf,
        shangx: this.shangx,
        shangy: this.shangy,
        zuox: this.zuox,
        zuoy: this.zuoy,
        youx: this.youx,
        youy: this.youy,
        xiax: this.xiax,
        xiay: this.xiay,
        zuixiaof: bestDirection.f,
        zuixiaofangxiangx: bestDirection.x,
        zuixiaofangxiangy: bestDirection.y,
        mubiaox: this.mubiaox,
        mubiaoy: this.mubiaoy,
        juesex: this.juesex,
        juesey: this.juesey
    };
    
    // 7. 记录要去的点(在发送事件之前)
    this.zuoguo.push({x: bestDirection.x, y: bestDirection.y});
    
    // 8. 发送绘制事件
    director.emit('xiaobing_sxzy_gezi', directionData);
    
    // 9. 检查是否到达目标
    if (bestDirection.x === this.mubiaox && bestDirection.y === this.mubiaoy) {
        console.log("🎯 到达目标!");
        return;
    }
    
    // 10. 继续递归
    console.log(`继续前进到[${bestDirection.x},${bestDirection.y}]`);
    this.huoqushangxiazuoyou(bestDirection.x, bestDirection.y, bestDirection.g);
}
}
相关推荐
林夕sama4 小时前
MySQL的学习笔记
笔记·学习·mysql
徐某人..4 小时前
网络编程学习--第一天
arm开发·单片机·学习·arm
TL滕5 小时前
从0开始学算法——第十一天(字符串基础算法)
笔记·学习·算法
Hello_Embed5 小时前
FreeRTOS 入门(二十六):队列创建与读写 API 实战解析
笔记·学习·操作系统·嵌入式·freertos
2201_757830875 小时前
JS的学习
前端·javascript·学习
xixixi777775 小时前
CRNN(CNN + RNN + CTC):OCR识别的经典之作
人工智能·rnn·学习·架构·cnn·ocr·图像识别
三杯五岳6 小时前
鸿蒙手机游戏开发学习 - 四顶棋(二打一)
学习·游戏源码·鸿蒙原生
dragoooon346 小时前
[C++——lesson16.STL 学习——【string的模拟实现】]
c++·学习
思成不止于此6 小时前
【MySQL 零基础入门】DQL 核心语法(一):学生表基础查询与聚合函数篇
数据库·笔记·学习·mysql