LayaAir之制作迷宫

最近看到一篇博客,也是制作迷宫的,我仔细看了一下,里面涉及一个算法--并查集(不相交集合),没有听过,就打算练习一下,由于最近又在使用LayaAir,就打算用它来写。

先看我之前看的那两篇文章:链接1链接2

我使用的是LayaAir2.2.0beta4

效果图:

1、创建工程,新建场景

新建一个脚本,脚本继承Laya.Script,把该脚本添加到场景里

2、画地图、画蓝色方块、红色方块

//画地图
this.m_lineBox = new Laya.Sprite();
this.setPos(this.m_lineBox,0,0);
this.setzOrder(this.m_lineBox,0);
this.owner.addChild(this.m_lineBox);
for (let i = 0; i < 16; i++) {
    this.m_lineBox.graphics.drawLine(100,100+30*i,550,100+30*i,"#ffffff",2);
    this.m_lineBox.graphics.drawLine(100+30*i,100,100+30*i,550,"#ffffff",2);
}
//画蓝色方块
this.m_blue = new Laya.Sprite();
this.m_blue.size(20,20);
this.setPos(this.m_blue,105,105);
this.setzOrder(this.m_blue,1);
this.owner.addChild(this.m_blue);
this.m_blue.graphics.drawRect(0,0,20,20,"#003dff","#003dff",1);
//画红色色方块
this.m_red = new Laya.Sprite();
this.m_red.size(20,20);
this.setPos(this.m_red,105+420,105+420);
this.setzOrder(this.m_red,0);
this.owner.addChild(this.m_red);
this.m_red.graphics.drawRect(0,0,20,20,"#ff0400","#ff0400",1);
//设置位置
private setPos(object:Laya.Sprite,x:number,y:number):void{
    object.pos(x,y);
}
//设置层级
private setzOrder(object:Laya.Sprite,value:number):void{
    object.zOrder = value;
}

3、移动蓝色方块

//键盘控制
onKeyDown(e:Laya.Event){
    //蓝色方块移动
    switch (e.keyCode) {
        case 37:
            this.moveObject(this.m_blue,-30,0);     
            break;
        case 38:
            this.moveObject(this.m_blue,0,-30);
            break;
        case 39:
            this.moveObject(this.m_blue,30,0);
            break;
        case 40:
            this.moveObject(this.m_blue,0,30);
            break;
    }
}
//移动对象
private moveObject(object:Laya.Sprite,x:number,y:number):void{
    //判断能否移动
    if(this.judgeMove(object,x,y)){
        let toX = object.x+x;
        let toY = object.y+y;
        this.setPos(object,toX,toY);
        //判断是否到达终点--于红色方块重合
        if(this.m_blue.x==this.m_red.x&&this.m_blue.y==this.m_red.y){
            console.log("过关了!");
            //初始化蓝色方块
            this.setPos(this.m_blue,105,105);
            //清理地图
            this.m_lineBox.graphics.clear();
            //重画地图
            for (let i = 0; i < 16; i++) {
                this.m_lineBox.graphics.drawLine(100,100+30*i,550,100+30*i,"#ffffff",2);
                this.m_lineBox.graphics.drawLine(100+30*i,100,100+30*i,550,"#ffffff",2);
            }
            //初始化节点数组
            this.m_mapInfoAry.forEach(e => {
                e.value = -1;
                e.parent = null;
                e.up = false;
                e.down = false;
                e.left = false;
                e.right = false;
            });
            //初始化起始点、终止点
            this.m_begin = new Laya.Point(this.m_blue.x-105,this.m_blue.y-105);
            this.m_end = new Laya.Point(this.m_red.x-105,this.m_red.y-105);
            //创建迷宫
            this.createMaze(this.m_begin,this.m_end);
        }
    }  
}
//判断移动
private judgeMove(object:Laya.Sprite,valueX:number,valueY:number):boolean{
    let toX:number = object.x+valueX;
    let toY:number = object.y+valueY;
    //判断是否出界
    if(toX>=105&&toX<=525&&toY>=105&&toY<=525){
        let nowX = Math.floor((object.x-105) / 30);
        let nowY = Math.floor((object.y-105) / 30);
        let nowNodeInfo = this.m_mapInfoAry[nowY*15+nowX];
        //判断是否相通
        if(valueX>0&&nowNodeInfo.right){
            return true;
        }
        else if(valueX<0&&nowNodeInfo.left){
            return true;
        }
        else if(valueY>0&&nowNodeInfo.down){
            return true;
        }
        else if(valueY<0&&nowNodeInfo.up){
            return true;
        }
        return false;
    }else{
        return false;
    }
}

 

4、创建节点类,创建节点数组,初始化起始点、终止点

class NodeInfo{
    public value:number;//孩子数
    public parent:NodeInfo;//父亲
    public up:boolean;//上面是否打通
    public down:boolean;//下面是否打通
    public left:boolean;//左面是否打通
    public right:boolean;//右面是否打通

    constructor(value:number){
        this.value = value;
        this.parent = null;
        this.up = false;
        this.down = false;
        this.left = false;
        this.right = false;
    }
}
//初始化起始点、终止点
this.m_begin = new Laya.Point(this.m_blue.x-105,this.m_blue.y-105);
this.m_end = new Laya.Point(this.m_red.x-105,this.m_red.y-105);
//初始化节点数组
for (let i = 0; i < 225; i++) {
    this.m_mapInfoAry.push(new NodeInfo(-1));
}

4、画迷宫(用到了并查集)

private createMaze(begin:Laya.Point,end:Laya.Point):void{
    begin.x = Math.floor(begin.x / 30);
    begin.y = Math.floor(begin.y / 30);
    end.x = Math.floor(end.x / 30);
    end.y = Math.floor(end.y / 30);
    
    let beginNode:NodeInfo = this.m_mapInfoAry[begin.y*15+begin.x];
    let endNode:NodeInfo = this.m_mapInfoAry[end.y*15+end.x];
    
    while(true){
        let R_Num = Tool.GetRandomInt(0,224);
        let R_NodeInfo = this.m_mapInfoAry[R_Num];

        let dAry:Array<number> = [];
        if(R_Num%15>0&&this.limitABUnion(R_Num-1,R_NodeInfo)){
            dAry.push(1);
        }
        if(R_Num%15<14&&this.limitABUnion(R_Num+1,R_NodeInfo)){
            dAry.push(2);
        }
        if(Math.floor(R_Num/15)>0&&this.limitABUnion(R_Num-15,R_NodeInfo)){
            dAry.push(3);
        }
        if(Math.floor(R_Num/15)<14&&this.limitABUnion(R_Num+15,R_NodeInfo)){
            dAry.push(4);
        }
        if(dAry.length!=0){
            let dValue = Tool.GetRandomInt(0,dAry.length-1);
            let tempNode:NodeInfo;
            switch (dAry[dValue]) {
                case 1:
                    tempNode = this.m_mapInfoAry[R_Num-1];
                    R_NodeInfo.left = true;
                    tempNode.right = true;
                    break;
                case 2:
                    tempNode = this.m_mapInfoAry[R_Num+1];
                    R_NodeInfo.right = true;
                    tempNode.left = true;
                    break;
                case 3:
                    tempNode = this.m_mapInfoAry[R_Num-15];
                    R_NodeInfo.up = true;
                    tempNode.down = true;
                    break;
                case 4:
                    tempNode = this.m_mapInfoAry[R_Num+15];
                    R_NodeInfo.down = true;
                    tempNode.up = true;
                    break;
            }
            this.mopLine(R_Num%15*30+100,Math.floor(R_Num/15)*30+100,dAry[dValue]);
            this.willABUnion(R_NodeInfo,tempNode,null);
            if(this.judgeABUnion(beginNode, endNode))break;
        }
    }
}
//擦线
private mopLine(x:number,y:number,value:number){
    switch (value) {
        case 1:
            this.m_lineBox.graphics.drawLine(x,y,x,y+30,"#000000",2);
            break;
        case 2:
            this.m_lineBox.graphics.drawLine(x+30,y,x+30,y+30,"#000000",2);
            break;
        case 3:
            this.m_lineBox.graphics.drawLine(x,y,x+30,y,"#000000",2);
            break;
        case 4:
            this.m_lineBox.graphics.drawLine(x,y+30,x+30,y+30,"#000000",2);
            break;
    }
}
//限制AB联盟
private limitABUnion(Aindex:number,_B:NodeInfo):boolean{
    let A = this.m_mapInfoAry[Aindex];
    let B = _B;
    if(!this.judgeABUnion(A,B))return true;
    else return false;
}
//将AB联盟
private willABUnion(A:NodeInfo,B:NodeInfo,C:NodeInfo):void{
    if(A.parent!=null){
        if(B.parent!=null){
            this.willABUnion(A.parent,B.parent,B);
        }else{
            this.willABUnion(A.parent,B,B);
        }
    }else{
        if(B.parent!=null){
            this.willABUnion(A,B.parent,B);
        }else{
            if(A.value==B.value){
                A.parent = B;
                B.value += A.value; 
            }else{
                if(A.value<B.value){
                    B.parent = A;
                    A.value += B.value; 
                }else{
                    A.parent = B;
                    B.value += A.value;
                }
            }
        }
    }
}
//判断AB联盟
private judgeABUnion(A:NodeInfo,B:NodeInfo):boolean{
    if(A.parent!=null){
        if(B.parent!=null){
            return this.judgeABUnion(A.parent,B.parent);
        }else{
            return this.judgeABUnion(A.parent,B);
        }
    }else{
        if(B.parent!=null){
            return this.judgeABUnion(A,B.parent);
        }else{
            if(A==B)return true;
            else return false;
        }
    }
}
//随机数
public static GetRandomInt(min: number, max: number): number 
{
    var Gap = max - min;
    var Rand = Math.random();
    return(min + Math.round(Rand * Gap));
}

到此为止迷宫就做完了

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值