如何在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
相关产品推荐
相关产品推荐

