请教一下实现汉诺塔的代码的编写思路

在学习递归的时候试着写了一下汉诺塔,但是把递归逻辑变成代码的过程似乎有问题。我的思路是:

  • 根据递归逻辑,重复的内容是:哪个盘子,从哪个柱子,移动到哪个柱子,所以需要的参数是:盘子的数量、盘子现在所在柱子的编号、盘子要放到的柱子的编号,所以函数定义为move(int n, char from, char to),测试调用时from的值为'A',to的值为'C'

  • 对函数分类讨论,如果n=1,则syso(n+"从"+from+"到"+to)来代表第一个盘子的移动;如果n>1,则执行以下三步:
    n-1个盘子从A到B:move(n, 'A', 'B')
    第n个盘子从A到C:syso(n+"从A到C")
    n-1个盘子从B到C:move(n, 'B', 'C')

  • 完整的代码如下:

package algorithm;

import java.util.Scanner;

public class Hannuo {

    void play(int n, char from, char to) {
        if(n==1)
            System.out.println("["+n+"]:"+from+">>>>"+to);
        else {
            this.play(n-1, 'A', 'B');
            System.out.println("["+n+"]:A>>>>C");
            this.play(n-1, 'B', 'C');
        }
    }
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        Hannuo h = new Hannuo();
        while(true) {
            System.out.println("请输入盘数:");
            int n=sc.nextInt();
            if(n==0)
                break;
            h.play(n, 'A', 'C');
        }
        sc.close();
    }
}

但是n=3的情况下的执行结果就不对,我去网上查了以下其他人的,函数都是定义了4个输入参数,多了一个“过渡柱子”的参数,但是根据递归逻辑,移动的过程就是哪个盘子、从哪个柱子、到哪个柱子,没有提到第三个柱子,所以想不明白为什么正确的代码有第三个柱子作为参数,以及为什么我自己设计的代码逻辑错在哪个地方,希望能帮忙指导一下

既然你要用递归的思想,那么你就要先明白递归的思想到底和循环差在哪里
先说循环,循环是个正向的逻辑,你必须首先知道第1步要干什么,然后你要知道第k+1步比第k步多做了什么,然后代入,开始迭代,从1迭代到n
而递归是反向的逻辑
一开始并不管第一步要干什么,只关心从第k-1步到第k步到底怎么实现,然后往回倒,一直倒到有一个确定的结果为止
-=-=-=-
那么回到汉诺塔的问题
假如ABC三个柱子,你要把A柱子上的x个片移动到C柱子上,那么首先要把A柱子上的x-1个片移动到B柱子上作为中转,然后把最下面一个移动到C柱子上,再把B柱子上的x-1个片移动到C柱子上。假如这是第k步要做的事情,那么第k-1步是要怎么把x-1个从A移动到B,第k-2步是如何把x-2个片从B移动到A,以此类推,一直到只剩一个片就直接移动

  • 这有个类似的问题, 你可以参考下: https://ask.csdn.net/questions/7546011
  • 除此之外, 这篇博客: 暴力破解算法思想(1)中的 但是,在比赛中,我们的目的就是想出一个实用、快速、稳定、有效的方法去得到我们想要的结果,一道题你也许会想出很精妙的解决办法, 直接得到结果,但是耗时太长了,所以,在比赛的时候需要“灵活”一下,拿到这个题目后,我们肯定是不能很容易想出答案的,因为可能的情况太多,所以我们需要编程,利用所给条件,我们一定可以将可能的情况减少,在很少的可能结果中挑选一个正确的答案就变得容易得多,下面我们来看一看如何去写: 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
  • package violentCracking;
    
    public class repeat {
    
    	public static void main(String[] args) {
    		// 运用重复检测的方法去做
    		for (int i = 1; i < 100; i++) {
    			int a =i*i*i;
    			int b =a*i;
    			if ((a+"").length()!=4) {//判断立方长度是否为4
    				continue;
    			}
    			if ((b+"").length()!=6) {//判断4次方长度是否为6
    				continue;
    			}
    			
    			System.out.println("当前年龄"+i+"  年龄的三次方 "+a+" 年龄的四次方 "+b);
    		}
    
    	}
    
    }

    得到的结果是

    当前年龄18  年龄的三次方 5832 年龄的四次方 104976
    当前年龄19  年龄的三次方 6859 年龄的四次方 130321
    当前年龄20  年龄的三次方 8000 年龄的四次方 160000
    当前年龄21  年龄的三次方 9261 年龄的四次方 194481