JS A星算法

就那么随手一写代码质量不高,纯粹写demo。


const { ccclass, property } = cc._decorator;

const cost1: number = 10
const cost2: number = 14
const childMap: Array<Array<number>> = [
    [-1, 0],
    [-1, -1],
    [0, -1],
    [1, -1],
    [1, 0],
    [1, 1],
    [0, 1],
    [-1, 1]
]
@ccclass
export default class NewClass extends cc.Component {

    @property(cc.Integer)
    mapWidth: number = 10

    @property(cc.Integer)
    mapHeight: number = 10

    @property(cc.SpriteFrame)
    normalNode: cc.SpriteFrame = null
    startNode: cc.Node = null
    endNode: cc.Node = null
    mapArr: Array<Array<number>> = []
    nodeArr: Array<Array<cc.Node>> = []
    openTable: Object = {}
    closeTable: Object = {}
    // LIFE-CYCLE CALLBACKS:
    oderIdx: number = 2
    // onLoad () {}

    start() {
        this.generiteMap()
    }

    generiteMap() {
        let x = -1334 / 2 + 62 / 2 + 20
        let y = 750 / 2 - 62 / 2 - 20
        for (let i = 0; i < this.mapHeight; ++i) {
            this.mapArr.push([])
            this.nodeArr.push([])
            for (let j = 0; j < this.mapWidth; ++j) {
                let node = new cc.Node()
                node.parent = this.node
                let cp = node.addComponent(cc.Sprite)
                cp.spriteFrame = this.normalNode
                let n = Math.round(Math.random() * 3)
                if (n == 0) {
                    node.color = cc.color(0, 0, 0, 255)
                } else {
                    node.addComponent(cc.Button)
                    node.on('click', function (e) {
                        if (this.startNode && this.endNode && this.oderIdx % 2 == 0) {
                            this.startNode.color = cc.Color.WHITE
                            this.endNode.color = cc.Color.WHITE
                        }
                        if (this.oderIdx % 2 == 0) {
                            node.color = cc.Color.GREEN
                            this.startNode = node
                        } else {
                            this.endNode = node
                            node.color = cc.Color.BLUE
                            this.startFinding()
                        }
                        ++this.oderIdx
                    }, this)
                }
                this.nodeArr[i].push(node)
                this.mapArr[i].push(n)
                node.position = cc.v2(x + (node.width + 10) * j, y - (node.height + 10) * i)

            }
        }
    }

    startFinding(): void {
        let startPos = this.getIdxByNode(this.startNode)
        let endPos = this.getIdxByNode(this.endNode)
        let result:Object = null 
        let found:boolean = false 
        this.insertToOpen(this.generiteChild(startPos,startPos,endPos))
        while(Object.keys(this.openTable).length > 0){
            let cPoint = this.getBestPointInOpen()
            if(cPoint['point']['x'] == endPos.x && cPoint['point']['y'] == endPos.y){
                found = true 
                result = cPoint
                break 
            } 
            this.removeInOpen(cPoint)
            this.insertToClose(cPoint)
            let children = this.generiteChildren(cPoint['point'],endPos)
            let currentPoint = cPoint['point']
            for(let pt of children){
                let point = pt['point']
                if(!this.inOpen(pt['point'])){
                    cc.log(cPoint['point']['x'], cPoint['point']['y'],'open')
                    
                    let g = Math.abs(point.x - currentPoint.x) + Math.abs(point.y - currentPoint.y) <= 1 ? cost1 : cost2
                    let h = Math.pow(Math.abs(point.x - endPos.x) + 1, 2) + Math.pow(Math.abs(point.y - endPos.y) + 1, 2)
                    let f = g + h
                    cPoint['g'] = g
                    cPoint['f'] = f
                    cPoint['h'] = h
                    pt['parent'] = cPoint
                    this.insertToOpen(pt)
                }else {
                    cc.log(cPoint['point']['x'], cPoint['point']['y'], 'close')
                    
                    let g = Math.abs(point.x - currentPoint.x) + Math.abs(point.y - currentPoint.y) <= 1 ? cost1 : cost2
                    if(pt['g'] > g){
                        pt['g'] = g 
                        pt['f'] = g + pt['h']
                        pt['parent'] = cPoint
                    }
                }
            }
            if(this.inOpen(endPos)){
                result = this.openTable['x'+endPos.x +'y'+endPos.y]
            }
        }
        while(result.hasOwnProperty('parent')){
            let p = result['point']
            if(p.x != endPos.x || p.y != endPos.y)
                this.nodeArr[p.x][p.y].color = cc.Color.MAGENTA
            result = result['parent']
        }
    }

    getIdxByNode(node: cc.Node) {
        let x = -1334 / 2 + 62 / 2 + 20
        let y = 750 / 2 - 62 / 2 - 20
        let p = node.position
        y = (y - p.y) / (62 + 10)
        x = (p.x - x) / (62 + 10)
        return cc.v2(Math.floor(y), Math.floor(x))
    }

    insertToTable(table: Object, pt: Object) {
        table['x' + pt['point']['x'] + 'y' + pt['point']['y']] = pt
    }

    insertToOpen(pt: Object) {
        this.insertToTable(this.openTable, pt)
    }

    insertToClose(pt: Object) {
        this.insertToTable(this.closeTable, pt)
    }
    removeInOpen(pt:Object){
        delete this.openTable['x'+pt['point']['x'] + 'y' + pt['point']['y']]
    }
    inOpen(pt: cc.Vec2) {
        return this.openTable.hasOwnProperty('x' + pt.x + 'y' + pt.y)
    }

    inClose(pt: cc.Vec2) {
        return this.closeTable.hasOwnProperty('x' + pt.x + 'y' + pt.y)
    }

    validPoint(pt: cc.Vec2) {
        return pt.x >= 0 && pt.x < this.mapHeight &&
            pt.y >= 0 && pt.y < this.mapWidth && this.mapArr[pt.x][pt.y] != 0 
    }
    
    getBestPointInOpen(){
        let max:number = Number.MAX_VALUE 
        let result:Object = null  
        for(let i in this.openTable){
            let obj = this.openTable[i]
            if(obj['f'] < max){
                max = obj['f']
                result = obj 
            }
        }
        return result
    }

    generiteChildren(pt: cc.Vec2,endp:cc.Vec2) {
        let result: Array<Object> = []
        for(let i of childMap){
            let p = cc.v2(pt.x + i[0] , pt.y + i[1])
            if(this.validPoint(p) &&! this.inClose(p)){
                result.push(this.generiteChild(p,pt,endp))
            }
        }
        return result
    }

    generiteChild(pt: cc.Vec2, startPos: cc.Vec2, endPos: cc.Vec2) {
        let g = Math.abs(pt.x - startPos.x) + Math.abs(pt.y - startPos.y) <= 1 ? cost1 : cost2
        let h = Math.pow(Math.abs(pt.x - endPos.x) + 1 , 2) + Math.pow(Math.abs(pt.y - endPos.y) + 1, 2)
        let f = g + h
        return {
            g: g,
            h: h,
            f: f,
            point: pt
        }
    }
    // update (dt) {}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值