汉诺塔自动解题动画中的iOS开发技巧

前段时间做了一道题,要求实现汉诺塔游戏的自动解题动画:

汉诺塔游戏应该都了解规则:

1、将盘子全部移动到塔C
2、每次只能移动一个圆盘;
3、大盘不能叠在小盘上面。

要求由用户输入盘子的数量,绘制盘子和塔,点击开始后自动解题,并以动画移动盘子的形式演示。

觉得还挺有意思的,而且在做的过程中也踩了一些坑,用了一些技巧和优化,因此记录下来。

效果:

汉诺塔解法

这道题中汉诺塔的解法本身并不是难点。

1、如果只有一个盘子,那就直接从A移动到C;
2、如果有两个盘子,那就要先把小盘子移动到B,然后大盘子移动到C,再把小盘子移动到C;
3、如果有三个盘子,那就要先把上面两个盘子移动到B(借助C的辅助),然后把底下的大盘子移动到C,然后把B上的两个盘子借助A移动到C;
……
4、如果有n个盘子,那就要先把上面n-1个盘子移动到B(借助C的辅助),然后把底下的大盘子移动到C,然后把B上的n-1盘子借助A移动到C。

综上所述,除了一个盘子的情况直接移动,其余都需要借助其他盘子的帮助,复杂情况虽然不一样,但是过程是递归不断重复的。

递归代码如下:

// 确定提交
- (void)submit {
    if ([self.numberField.text isEqualToString:@""]) {
        NSLog(@"未输入内容");
        UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"提示" message:@"您还未输入层数!" preferredStyle:UIAlertControllerStyleAlert];
        UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
        }];
        [alertController addAction:okAction];
        [self presentViewController:alertController animated:YES completion:nil];
    } else {
        self.diskNumber = [self.numberField.text integerValue];
        self.moveCount = 0;
        [self hanoiWithDisk:self.diskNumber towers:@"A" :@"B" :@"C"];
        NSLog(@">>移动了%ld次", self.moveCount);
    }
}

// 移动算法
- (void)hanoiWithDisk:(NSInteger)diskNumber towers:(NSString *)towerA :(NSString *)towerB :(NSString *)towerC {
    if (diskNumber == 1) {
  // 只有一个盘子则直接从A塔移动到C塔
        [self move:1 from:towerA to:towerC];
    } else {
        [self hanoiWithDisk:diskNumber-1 towers:towerA :towerC :towerB];// 递归把A塔上编号1~diskNumber-1的盘子移动到B塔,C塔辅助
        [self move:diskNumber from:towerA to:towerC];// 把A塔上编号为diskNumber的盘子移动到C塔
        [self hanoiWithDisk:diskNumber-1 towers:towerB :towerA :towerC];// 递归把B塔上编号1~diskNumber-1的盘子移动到C塔,A塔辅助
    }
}

// 移动过程
- (void)move:(NSInteger)diskIndex from:(NSString *)fromTower to:(NSString *)toTower {
    NSLog(@"第%ld次移动:把%ld号盘从%@移动到%@", ++self.moveCount, diskIndex, fromTower, toTower);
}

三层盘子时:

四层盘子时:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值