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);
}
}