ios 一个简单的迷宫生成算法.(以及用户操作)

假设迷宫为10行10列,入口为(0,0),出口为(9,9)如何随机生成一个10*10点的矩阵迷宫,并且保证入口点与出口点之间有通路呢?

下边上代码,代码有些乱,但是思路简单,就是记录与回溯,如果最后回溯到(0,0),说明没有通路,继续循环整个代码流程即可.

#import "ViewController.h"
@interface ViewController ()
@property(strong,nonatomic)UIGravityBehavior *btnGra;
@property(strong,nonatomic)UIButton*lastBtn;
@property(strong,nonatomic)NSMutableArray *mazeArr;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
}
-(void)viewDidAppear:(BOOL)animated{
    [super viewDidAppear:animated];
    //    [self colligeTest];
    [self creatMaze];
    //    [self startGraManager];
}
#pragma mark - 碰撞检测
-(void)colligeTest{
    self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
    [self collige];
}
-(void)collige{
    //重力检测
    UIGravityBehavior *gra = [[UIGravityBehavior alloc] init];
    [gra addItem:self.btn];
    self.btnGra = gra;
    //碰撞检测
    UICollisionBehavior *cli  = [[UICollisionBehavior alloc] init];
    [cli addItem:self.btn];
    [cli addItem:self.progress];
    [cli addItem:self.seg];
    //加入边缘
//    cli.translatesReferenceBoundsIntoBoundary = YES;
    //外边界
    [cli addBoundaryWithIdentifier:@"1" fromPoint:CGPointMake(0, 50) toPoint:CGPointMake(self.view.frame.size.width, 50)];
    [cli addBoundaryWithIdentifier:@"2" fromPoint:CGPointMake(self.view.frame.size.width, 50) toPoint:CGPointMake(self.view.frame.size.width, self.view.frame.size.height-50)];
    [cli addBoundaryWithIdentifier:@"3" fromPoint:CGPointMake(self.view.frame.size.width, self.view.frame.size.height-50) toPoint:CGPointMake(0, self.view.frame.size.height-50)];
    [cli addBoundaryWithIdentifier:@"4" fromPoint:CGPointMake(0, self.view.frame.size.height-50) toPoint:CGPointMake(0, 50)];
    //内边界
    [cli addBoundaryWithIdentifier:@"5" fromPoint:CGPointMake(200, 300) toPoint:CGPointMake(self.view.frame.size.width-200, 300)];
    [cli addBoundaryWithIdentifier:@"6" fromPoint:CGPointMake(self.view.frame.size.width-200, 300) toPoint:CGPointMake(self.view.frame.size.width-200, self.view.frame.size.height-300)];
    [cli addBoundaryWithIdentifier:@"7" fromPoint:CGPointMake(self.view.frame.size.width-200, self.view.frame.size.height-300) toPoint:CGPointMake(200, self.view.frame.size.height-300)];
    [cli addBoundaryWithIdentifier:@"8" fromPoint:CGPointMake(200, self.view.frame.size.height-300) toPoint:CGPointMake(200, 300)];
    
    //开始碰撞
    [self.animator addBehavior:gra];
    [self.animator addBehavior:cli];
}
#pragma mark - 重力检测,改变方向
-(CMMotionManager *)graManager{
    if (!_graManager) {
        _graManager = [[CMMotionManager alloc] init];
    }
    return _graManager;
}
-(void)startGraManager{
    if ([self.graManager isAccelerometerAvailable]==YES) {
        [self.graManager setAccelerometerUpdateInterval:0.06];
        [self.graManager startAccelerometerUpdatesToQueue:[NSOperationQueue currentQueue] withHandler:^(CMAccelerometerData * _Nullable accelerometerData, NSError * _Nullable error) {
            double x = accelerometerData.acceleration.x;
            double y = accelerometerData.acceleration.y;
            self.btnGra.gravityDirection = CGVectorMake(x, -y);
            if (fabs(x)>fabs(y)) {
                //水平移动变化大
                if (x>0) {
                    NSLog(@"向右 x = %f",x);
                }else if(x<=0){
                    NSLog(@"向左 x = %f",x);
                }
            }else{
                //竖直移动变化大
                if (y>0) {
                    NSLog(@"向下 y = %f",y);
                }else if(y<0){
                    NSLog(@"向上 y = %f",y);
                }
            }
        }];
    }
}
#pragma mark - 迷宫
-(void)creatMaze{
    //视图隐藏
    self.btn.hidden = YES;
    self.progress.hidden = YES;
    self.seg.hidden = YES;
    
    
    //先创建迷宫10*10
    int line = 10;
    int column = 10;
    
    //将10,10 扩充为12,12那么原迷宫每个点都有上下左右方向是可以选择的
    //0为通道,1为障碍,控制1的数量,不然可能没有通道
    int maze[line+2][column+2];
    int useMaze[line][column];
    for (int w = 0; w<line+2; w++) {
        for (int h = 0; h<column+2; h++) {
            //因为原迷宫四周不可走,相当于一圈围墙,所以设置为1
            if (w ==0||h==0||w==line+1||h == column+1) {
                maze[w][h] = 1;
            }else{
                //不是围墙,是原迷宫的点
                //1,1为起点,10,10为终点
                if ((w==1&&h==1)||(w==line&&h==column)) {
                    maze[w][h] = 0;
                }else{
                    //其他的随机0或1,在这里控制下1的数量几率,障碍太多可能没有通道
                    int c = arc4random()%4;
                    if (c==0) {
                        maze[w][h] = 1;
                    }else {
                        maze[w][h] = 0;
                    }
                    
                }
                
            }
            printf("%d ", maze[w][h]);
            //            NSLog(@"%d",maze[w][h]);
        }
        NSLog(@"\n");
    }
    
    self.mazeArr = [[NSMutableArray alloc] init];
    for (int i = 0 ; i<line; i++) {
        NSMutableArray*lineArr = [[NSMutableArray alloc] init];
        for (int j = 0; j<column; j++) {
            useMaze[i][j] = maze[i+1][j+1];
            [lineArr addObject:[NSString stringWithFormat:@"%d",useMaze[i][j]]];
        }
        [self.mazeArr addObject:lineArr];
    }
    NSLog(@"\n迷宫完成\n");
    //记录每一步的行,列坐标,还有每一步的方向
    int x[10*10];
    //第一步,起始点的横坐标
    x[0] = 1;
    int y[10*10];
    //第一步,起始点的纵坐标
    y[0] = 1;
    int head[10*10];
    //第一步
    head[0] = 1;
    int step = 0;
    int nowx =1;
    int nowy =1;
    
    //上左下右 1,2,3,4
    //从1,1开始向终点10,10逼近
    while (!(nowx==10&&nowy==10)) {
        //        NSLog(@"step = %d nowx :%d nowy :%d",step,nowx,nowy);
        int tempx = nowx;
        int tempy = nowy;
        //上左下右移动时,判断是否已走过
        for (int i = 1; i<5; i++) {
            if (i == 4){
                if (maze[nowy][nowx+1]==0) {
                    tempx = nowx+1;
                    break;
                }
            }else if (i == 3){
                if (maze[nowy+1][nowx]==0) {
                    tempy = nowy+1;
                    break;
                }
            }
            else if (i == 2){
                if (maze[nowy][nowx-1]==0) {
                    tempx = nowx-1;
                    break;
                }
            }else if (i==1) {
                if (maze[nowy-1][nowx]==0) {
                    tempy = nowy-1;
                    break;
                }
            }
        }
        //判断有没有移动
        //有移动的话,步数加一,不回溯,没有移动的话,步数减一,回溯到上一个节点.s
        if (tempx!=nowx||tempy!=nowy) {
            //可移动
            nowy = tempy;
            nowx = tempx;
            
            maze[nowy][nowx] = 1;
            
            step++;
            
            x[step] = nowx;
            y[step] = nowy;
            
        }else{
            x[step] = 0;
            y[step] = 0;
            
            step--;
            if (step>=0) {
                nowx = x[step];
                nowy = y[step];
            }else{
                NSLog(@"there is no path");
                break;
                
            }
            
        }
        
        
        
    }
    
    NSLog(@"short step = %d" ,step);
    if (step>=0) {
        for (int i = 0; i<100; i++) {
            if (x[i]!=0&&y[i]!=0&&x[i]<=10&&y[i]<=10) {
                printf("(%d,%d)",x[i],y[i]);
            }
        }
        //step>0说明迷宫有通路
        //开始制作迷宫视图
        CGFloat width = self.view.frame.size.width/10;
        UIView *bgView = [[UIView alloc] initWithFrame:CGRectMake(0, self.view.frame.size.height-self.view.frame.size.width, self.view.frame.size.width, self.view.frame.size.width)];
        bgView.layer.borderWidth = 1;
        bgView.layer.borderColor = [UIColor redColor].CGColor;
        [self.view addSubview:bgView];
        
        for (int i = 0 ; i<line; i++) {
            for (int j = 0 ; j<column; j++) {
                UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
                btn.frame = CGRectMake(j*width, i*width, width, width);
                if (useMaze[i][j]==1) {
                    btn.backgroundColor = [UIColor grayColor];
                    btn.userInteractionEnabled = NO;
                }else{
                    btn.backgroundColor = [UIColor whiteColor];
                    btn.userInteractionEnabled = YES;
                    [btn addTarget:self action:@selector(clickbtn:) forControlEvents:UIControlEventTouchUpInside];
                }
                if (i==0&&j==0) {
                    [btn setTitle:@"起点" forState:UIControlStateNormal];
                    [btn.titleLabel setFont:[UIFont systemFontOfSize:10]];
                    self.lastBtn=btn;
                    btn.backgroundColor = [UIColor  greenColor];
                }else if (i==9&&j==9){
                    [btn setTitle:@"终点" forState:UIControlStateNormal];
                    [btn.titleLabel setFont:[UIFont systemFontOfSize:10]];
                }
                [bgView addSubview:btn];
            }
        }
        
        
        
    }
}
-(void)clickbtn:(UIButton*)btn{
    //同行,中间无障碍间隔可移动
    //同列,中间无障碍间隔可移动
    CGFloat width = self.view.frame.size.width/10;
    BOOL canmove = YES;
    int x = btn.frame.origin.x/width;
    int y = btn.frame.origin.y/width;
    if (btn.frame.origin.x==self.lastBtn.frame.origin.x) {
        if (btn.frame.origin.y>self.lastBtn.frame.origin.y) {
            for (int i = self.lastBtn.frame.origin.y/width; i<=btn.frame.origin.y/width; i++) {
                NSString *str = [self.mazeArr[i] objectAtIndex:x];
                if ([str isEqualToString:@"1"]) {
                    canmove = NO;
                    break;
                }
            }
            if (canmove) {
                self.lastBtn.backgroundColor = [UIColor whiteColor];
                self.lastBtn = btn;
                self.lastBtn.backgroundColor = [UIColor greenColor];
            }
        }else if (btn.frame.origin.y<self.lastBtn.frame.origin.y){
            for (int i = btn.frame.origin.y/width; i<=self.lastBtn.frame.origin.y/width; i++) {
                NSString *str = [self.mazeArr[i] objectAtIndex:x];
                if ([str isEqualToString:@"1"]) {
                    canmove = NO;
                    break;
                }
            }
            if (canmove) {
                self.lastBtn.backgroundColor = [UIColor whiteColor];
                self.lastBtn = btn;
                self.lastBtn.backgroundColor = [UIColor greenColor];
            }
        }
    }else if (btn.frame.origin.y==self.lastBtn.frame.origin.y){
        if (btn.frame.origin.x>self.lastBtn.frame.origin.x) {
            for (int i = self.lastBtn.frame.origin.x/width; i<=btn.frame.origin.x/width; i++) {
                NSString *str = [self.mazeArr[y] objectAtIndex:i];
                if ([str isEqualToString:@"1"]) {
                    canmove = NO;
                    break;
                }
            }
            if (canmove) {
                self.lastBtn.backgroundColor = [UIColor whiteColor];
                self.lastBtn = btn;
                self.lastBtn.backgroundColor = [UIColor greenColor];
            }
        }else if (btn.frame.origin.x<self.lastBtn.frame.origin.x){
            for (int i = btn.frame.origin.x/width; i<=self.lastBtn.frame.origin.x/width; i++) {
                NSString *str = [self.mazeArr[y] objectAtIndex:i];
                if ([str isEqualToString:@"1"]) {
                    canmove = NO;
                    break;
                }
            }
            if (canmove) {
                self.lastBtn.backgroundColor = [UIColor whiteColor];
                self.lastBtn = btn;
                self.lastBtn.backgroundColor = [UIColor greenColor];
            }
        }
    }
    
    
    
    if (self.lastBtn.frame.origin.x/width==9&&self.lastBtn.frame.origin.y/width==9) {
        NSLog(@"恭喜你到达终点.");
    }
}
- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}


@end


有问题请加群:565191947

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值