假设迷宫为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