You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Java汉诺塔代码中实现分步塔状态展示?

解决汉诺塔分步状态展示问题

我懂你的需求——你已经实现了汉诺塔的移动步骤文本输出,但现在想在每一步移动后直观展示三个塔的当前状态对吧?其实核心就是给塔的状态做持久化存储,每次移动后更新并打印出来。咱们来一步步修改你的代码:

核心思路

  • 用二维数组存储三个塔的状态:每个子数组代表一个塔,数组元素对应塔的位置(0表示空,非0值表示盘子大小)。
  • 初始化时给第一个塔装满盘子,另外两个塔设为空。
  • 修改moveOneDisk方法:不再只是打印指令,而是实际更新塔的状态,然后打印步骤+当前状态。
  • 写一个辅助方法来生成格式化的塔状态字符串。

修改后的完整代码

Main类(无需改动)

public class Main { 
    // Creates a TowersOfHanoi puzzle and solves it. 
    public static void main(String[] args) { 
        TowersOfHanoi towers = new TowersOfHanoi(3); 
        towers.solve(); 
    } 
}

改进后的TowersOfHanoi类

public class TowersOfHanoi { 
    private int totalDisks; 
    private int[][] pegs; // 存储三个塔的状态,peg[0]对应第一个塔,以此类推
    private int stepCount = 0; // 步骤计数器

    //-----------------------------------------------------------------
    // Sets up the puzzle with the specified number of disks.
    //-----------------------------------------------------------------
    public TowersOfHanoi(int disks) { 
        totalDisks = disks; 
        // 初始化三个塔,每个塔有disks个位置,0表示空
        pegs = new int[3][disks]; 
        // 第一个塔从下到上放置disks, disks-1,...1(数组索引0是最底层)
        for (int i = 0; i < disks; i++) { 
            pegs[0][i] = disks - i; 
        } 
        // 另外两个塔初始化为全空
        for (int i = 0; i < disks; i++) { 
            pegs[1][i] = 0; 
            pegs[2][i] = 0; 
        } 
        // 打印初始状态
        System.out.println("初始状态: " + getPegStateString()); 
    } 

    //-----------------------------------------------------------------
    // Performs the initial call to moveTower to solve the puzzle.
    // Moves the disks from tower 1 to tower 3 using tower 2.
    //-----------------------------------------------------------------
    public void solve() { 
        moveTower(totalDisks, 1, 3, 2); 
    } 

    //-----------------------------------------------------------------
    // Moves the specified number of disks from one tower to another
    // by moving a subtower of n-1 disks out of the way, moving one
    // disk, then moving the subtower back. Base case of 1 disk.
    //-----------------------------------------------------------------
    private void moveTower(int numDisks, int start, int end, int temp) { 
        if (numDisks == 1) { 
            moveOneDisk(start, end); 
        } else { 
            moveTower(numDisks-1, start, temp, end); 
            moveOneDisk(start, end); 
            moveTower(numDisks-1, temp, end, start); 
        } 
    } 

    //-----------------------------------------------------------------
    // 实际移动盘子并打印步骤+当前塔状态
    //-----------------------------------------------------------------
    private void moveOneDisk(int start, int end) { 
        stepCount++; 
        // 转换为0-based索引(适配数组)
        int startPegIdx = start - 1; 
        int endPegIdx = end - 1; 

        // 找到起始塔最上方的盘子(从塔的顶部往下找第一个非空位置)
        int diskToMove = 0; 
        int startPos = -1; 
        for (int i = totalDisks - 1; i >= 0; i--) { 
            if (pegs[startPegIdx][i] != 0) { 
                diskToMove = pegs[startPegIdx][i]; 
                startPos = i; 
                break; 
            } 
        } 

        // 找到目标塔的放置位置(从塔的顶部往下找第一个空位置)
        int endPos = -1; 
        for (int i = totalDisks - 1; i >= 0; i--) { 
            if (pegs[endPegIdx][i] == 0) { 
                endPos = i; 
                break; 
            } 
        } 

        // 执行移动操作
        pegs[startPegIdx][startPos] = 0; 
        pegs[endPegIdx][endPos] = diskToMove; 

        // 格式化打印步骤和结果状态
        System.out.printf("Step %d: Move disk%d from peg%d to peg%d resulting %s%n", 
                          stepCount, diskToMove, startPegIdx, endPegIdx, getPegStateString()); 
    } 

    //-----------------------------------------------------------------
    // 生成格式化的塔状态字符串
    //-----------------------------------------------------------------
    private String getPegStateString() { 
        StringBuilder sb = new StringBuilder(); 
        for (int i = 0; i < 3; i++) { 
            sb.append("peg").append(i).append(": "); 
            // 遍历塔的每个位置(从底层到顶层)
            for (int disk : pegs[i]) { 
                sb.append(disk).append(" "); 
            } 
            sb.deleteCharAt(sb.length() - 1); // 移除末尾多余的空格
            if (i != 2) { 
                sb.append(" "); 
            } 
        } 
        return sb.toString(); 
    } 
}

代码说明

  • 状态存储:pegs二维数组的每个子数组对应一个塔,索引0是塔的最底层,索引totalDisks-1是塔的最顶层。
  • 移动逻辑:在moveOneDisk中,我们从塔的顶部(数组末尾)开始查找,找到第一个非空盘子作为待移动的盘子,再找到目标塔的第一个空位置完成放置。
  • 格式化输出:getPegStateString方法负责把塔的状态转换成你需要的字符串格式,确保输出和示例完全一致。

运行这段代码,你就能得到和你给出的示例完全相同的分步状态输出啦!

内容的提问来源于stack exchange,提问作者Best of Everything

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 06:31:10