java解决汉诺塔问题

问题遇到的现象和发生背景

用二维数组解决汉诺塔(梵天塔)
汉诺塔问题源于印度,梵天(天神)创造世界的时候做了三根金刚石柱子,在第一根柱子上按照从顺序摞着64片可以移动的黄金圆盘.梵天命令弟子们把圆盘按规则从第一根柱上移动至第三根柱上,堆放的顺序与原来完全相同。
圆盘移动规则是:
每次只能移动一片圆盘
小圆盘上不能放大圆盘
只能用三根柱子做中转
【基本要求】
1、用矩阵(二维数组)解决该问题
2、假设处理三个盘子
【实现提示】:可以分为三个阶段性任务:
1、将柱 A 最上面的n-1片圆盘移动到柱B,最少移动次数是f(n-1)
2、将留在柱A 上最大的圆盘移动到柱C,移动次数是1,
3、将柱B 上的n-1片圆盘移动到柱C,最少移动次数为f(n-1)
为了从整体上表示圆盘位置以及位置的变化,用数字1,2,…,n 表示从小到大的圆盘,并且将柱 A,B,C 上的圆盘标号存放在矩阵的第一列、第二列和第三列,这样,n 阶汉诺塔作为一个整体可用一个n×3矩阵S=[sij]n×3来表示.
若k号圆盘在矩阵的(i,j)位置,则定义sij=k (k=1,2),
否则取sij=0,表示此位置没有圆盘.这样的矩阵称为n阶汉诺塔的状态矩阵.移动圆盘的过程可用圆盘移动矩阵T=[tij]n×3来表示.用-表示圆盘移出,+表示圆盘移入,若k号圆由(i1,j1)位置移动到
(i2,j2)位置,则有t_i_1j_1=−k,t_i_2j_2=+k,其他元素都取为零.状态矩阵与圆盘移动矩阵可以各自独立构造,结构清晰,易于构造。
移动圆盘的过程可以用矩阵加法来表示。

问题相关代码,请勿粘贴截图
if(n==0) return;//如果n=0 返回
anoi(mid,left,right,n-1);//3.把中间n-1个盘子,从mid(第一个参数)借助right(第三个参数),移动到right(第二个参数)
我的解答思路和尝试过的方法

在圆盘移动过程中,用二维数组无法实现

我想要达到的结果

想要一个完整的,使用二维数组,解决此问题的代码和方法。

img


import java.util.Scanner;

public class Tester {
    
    //使用递归法求解含有n个不同大小盘子的汉诺塔移动路径,参数n为盘子数,把A塔上盘子全部移动到C塔上,B为过渡塔
    public static void recursionHanoi(int n,char A,char B,char C){
        if(n == 1){
            System.out.print(A+"——>"+C+"\n");    
        }
        else{
            recursionHanoi(n-1,A,C,B);         //使用递归先把A塔最上面的n-1个盘子移动到B塔上,C为过渡塔
            System.out.print(A+"——>"+C+"\n");       //把A塔中底下最大的圆盘,移动到C塔上
            recursionHanoi(n-1,B,A,C);         //使用递归把B塔上n-1个盘子移动到C塔上,A为过渡塔
        }
    }
    
    public static void noRecursionHanoi(int n){
        if(n<=0){
            throw new IllegalArgumentException("n must be >=1");
        }
        char[] hanoiPlate = new char[n];   //记录n个盘子所在的汉诺塔(hanoiPlate[1]='A'意味着第二个盘子现在在A上)
        char[][] next = new char [2][3];   //盘子下次会移动到的盘子的可能性分类
        int[] index = new int[n];

        //根据奇偶性将盘子分为两类
        for(int i=0;i<n;i=i+2){
            index[i]=0;
        }
        for(int i=1;i<n;i=i+2){
            index[i]=1;
        }

        //一开始所有盘子都在A上
        for(int i=0;i<n;i++){
            hanoiPlate[i]='A';
        }

        //n的奇偶性对移动方式的影响
        if(n%2==0){
            //数组下标为偶数的盘子移动目的塔,注意上面示例的标号为(1),其数组下标为0
            next[0][0]='B';
            next[0][1]='C';
            next[0][2]='A';
            //数组下标为奇数的盘子移动目的塔
            next[1][0]='C';
            next[1][1]='A';
            next[1][2]='B';
        }
        else
        {
            //数组下标为偶数的盘子移动目的塔,注意上面示例的标号为(1),其数组下标为0
            next[0][0]='C';
            next[0][1]='A';
            next[0][2]='B';
            //数组下标为奇数的盘子移动目的塔
            next[1][0]='B';
            next[1][1]='C';
            next[1][2]='A';
        }

        //开始移动
        for(int i=1;i<(1<<n);i++){                  //总共要执行2^n-1(1<<n-1)步移动
            int m=0;                                //m代表第m块盘子hanoiPlate[m]

            //根据步骤数i来判断移动哪块盘子以及如何移动
            for(int j=i;j>0;j=j/2){
                if(j%2!=0){    //此步骤光看代码代码有点抽象,建议手动写一下n = 2时的具体移动路径的j、m值变化
                    System.out.println("("+(m+1)+")"+hanoiPlate[m]+"->"+next[index[m]][hanoiPlate[m]-'A']);
                    hanoiPlate[m]=next[index[m]][hanoiPlate[m]-'A'];
                    break;                           //移动盘子后则退出这层循环
                }
                m++;
            }
        }
    }

    public static void main(String[] args){
        System.out.println("请输入盘子总数n:");
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();    
        recursionHanoi(n,'A','B','C');    
        System.out.println("非递归法结果:");
        noRecursionHanoi(n);    
        System.out.println();    
    }
}