汉诺塔:汉诺塔(又称河内塔)问题是源于印度一个古老传说的益智玩具。上帝创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上安大小顺序摞着64片黄金圆盘。上帝命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。
//汉诺塔
public class NewHanoi {
public static int tiers = 4; // tiers 层数
private static List<String> pagoda1 = new ArrayList<String>(); // 静态指针
private static List<String> pagoda2 = new ArrayList<String>();
private static List<String> pagoda3 = new ArrayList<String>();
// 映射,用来确定并打印塔的序号(使用角标),也可以使用 Map
private static List[] mapping = {pagoda1, pagoda2, pagoda3};
public static void main(String[] args) {
preparePagoda(pagoda1, tiers);
System.out.println("初始状态:");
printPagodas();
hanoi(tiers, pagoda1, pagoda2, pagoda3);
System.out.println("最后结果:");
printPagodas();
}
// --准备盘子(添加-字符串) (源塔)上
private static void preparePagoda(List<String> srcPagoda, int tiers) {
// 用于拼装塔层的容器
StringBuilder builder = new StringBuilder();
// 源塔的每一层加盘子,从底层开始, i ‘代表’盘子的直径大小,等于组成盘子的"^"个数
for(int i = tiers; i > 0; i--){
// 每一层由 2*tiers-1 个格子组成,代表盘子大小的"^"格子由空格隔开
for(int k = 0; k < tiers - i; k++) builder.append(" "); // 盘子左边的空格,数量为 [2*tiers-1-(2*i-1)]/2 = tiers-i, 右边相同
for(int j = 1; j <= 2*i-1; j++){ // 盘子所占格数
if(j % 2 == 1) builder.append("^"); // 间隔摆放
else builder.append(" ");
}
for(int k = 0; k < tiers - i; k++) builder.append(" "); // 盘子右边的空格
srcPagoda.add(builder.toString()); // 添加到塔上
builder.delete(0, builder.length()); // 下一循环前清空容器
}
}
// --打印塔的现状
private static void printPagodas(){
// 打印层数为三座塔-现状的最大高度
int len = Math.max(pagoda1.size(), Math.max(pagoda2.size(), pagoda3.size()));
// 用于-塔的空层显示
StringBuilder spaces = new StringBuilder();
spaces.append("-"); // --添加塔的左外框
for(int i = 0; i < 2*tiers-1; i++) spaces.append(" "); // 空层显示用空格
spaces.append("-\t"); // --添加塔的右外框和塔间间隔
for(int i = len - 1; i >= 0; i--){ // 从顶层开始
// 三座塔同一水平面的塔层放在同一行显示
// 当某个塔不存在此层时,List.get(index)会抛角标越界异常,使用try-catch处理:此层显示一层空格
try { System.out.print("-" + pagoda1.get(i) + "-\t");
} catch (Exception e1) { System.out.print(spaces);
}
try { System.out.print("-" + pagoda2.get(i) + "-\t");
} catch (Exception e) { System.out.print(spaces);
}
try { System.out.print("-" + pagoda3.get(i) + "-\t");
} catch (Exception e) { System.out.print(spaces);
}
System.out.print("\r\n");
}
}
// 这个方法(递归的核心方法)从指定的源塔上移动-指定数量的盘子-到指定的目标塔上
public static void hanoi(int moveNum, List<String> from, List<String> middle, List<String> to) {
if(moveNum == 1){ // 递归到移动一个盘子时,使用 move 方法
moveTheTopOne(from, to);
return;
}
// 将实现分为三步,一,将源塔底盘上方的所有盘子移至中间塔(递归);二,将底盘移到目标塔;三,将中间塔上的所有盘子移到目标塔上(递归)。
hanoi(moveNum - 1, from, to, middle);
moveTheTopOne(from, to);
hanoi(moveNum - 1, middle, from, to);
}
// 方法的名字就是他的作用
private static void moveTheTopOne(List<String> from, List<String> to) {
String theTopOne = from.remove(from.size() - 1);
to.add(theTopOne);
// 打印图形,每移动一下,打印图形显示
System.out.println("********** print ***********\r\n");
// 确定塔的序号
int fromNum = 0, toNum = 0;
for (int i = 0; i < mapping.length; i++) { // 遍历塔的数组
if (mapping[i] == from) {
fromNum = i+1;
}
if (mapping[i] == to) {
toNum = i+1;
}
}
System.out.println("从 " + fromNum + " 号塔往 " + toNum + " 号塔\r\n");
printPagodas(); // 打印图形
}
}
import javax.swing.*;
import java.awt.geom.*;
import java.awt.event.*;
import java.awt.*;
public class Hanio extends JApplet implements ActionListener, Runnable
{
/**
*diskNum是盘子的数量
*/
private int diskNum ;
/**
*各个组件的句柄
*/
private JButton begin, stop;
private JLabel lDiskNum;
private JTextField text;
JPanel pane;
/**
*定义一个线程句柄
*/
private Thread animate;
/**
*定义a,b,c三个柱子上是否有盘子,有哪些盘子
*/
private int adisk[];
private int bdisk[];
private int cdisk[];
public void init()
{
Container content = getContentPane();
content.setLayout(new BorderLayout());
lDiskNum = new JLabel("盘子的数目");
text = new JTextField(8);
begin = new JButton("开始");
begin.addActionListener(this);
stop = new JButton("停止");
stop.addActionListener(this);
pane = new JPanel();
pane.setLayout(new FlowLayout());
pane.add(lDiskNum);
pane.add(text);
pane.add(begin);
pane.add(stop);
content.add(pane, BorderLayout.SOUTH);
}
public void paint(Graphics g)
{
Graphics2D g2D = (Graphics2D)g;
Ellipse2D.Double ellipse;
g2D.setPaint(getBackground());
if(adisk != null)
{
/**
*消除以前画的盘子
*/
for(int j=adisk.length, i=0; --j>=0; i++ )
{
ellipse = new Ellipse2D.Double(20+i*5, 180-i*10, 180-i*10, 20);
g2D.fill(ellipse);
ellipse = new Ellipse2D.Double(220+i*5, 180-i*10, 180-i*10, 20);
g2D.fill(ellipse);
ellipse = new Ellipse2D.Double(420+i*5, 180-i*10, 180-i*10, 20);
g2D.fill(ellipse);
}
drawEllipse(g, 20, adisk);//画A组盘子
drawEllipse(g, 220, bdisk);//画B组盘子
drawEllipse(g, 420, cdisk);//画C组盘子
}
pane.repaint();
}
public void update(Graphics g)
{
paint(g);
}
/**画出椭圆代表盘子,g是图形环境,x是最下面的盘子的横坐标,
*arr是柱子数组
*/
public void drawEllipse(Graphics g,int x,int arr[])
{
Graphics2D g2D = (Graphics2D)g;
Ellipse2D.Double ellipse;
g2D.setPaint(Color.gray);
g2D.draw(new Line2D.Double(x+90, 10, x+90, 180));
for(int j=arr.length, i=0; --j>=0; i++ )
if(arr[j] != 0)
{
if(i%2 == 0)
g2D.setPaint(Color.blue);
else
g2D.setPaint(Color.red);
ellipse = new Ellipse2D.Double(x+i*5, 180-i*10, 180-i*10, 20);
g2D.fill(ellipse);
}
}
public void actionPerformed(ActionEvent e)
{
String command = e.getActionCommand();
if(command.equals("开始"))
{
/**
*进行初始化,开始的时候只有a柱子上有盘子,其他柱子都没有
*/
diskNum = Integer.parseInt(text.getText());
adisk = new int[diskNum];
for(int i=0; iadisk.length; i++)
adisk = 1;
bdisk = new int[diskNum];
for(int k=0; kbdisk.length; k++)
bdisk[k] = 0;
cdisk = new int[diskNum];
for(int i=0; icdisk.length; i++)
cdisk = 0;
repaint();
if(animate == null || !animate.isAlive())//创建一个线程
{
animate = new Thread(this);
animate.start();
}
}
if(command.equals("停止"))
{
for(int k=0; kbdisk.length; k++)
bdisk[k] = 0;
for(int i=0; icdisk.length; i++)
cdisk = 0;
repaint();
text.setText("");
animate = null;
}
}
/**
*线程方法,在此调用汉诺塔执行移动盘子操作
*/
public void run()
{
hanio(diskNum, 'A', 'B', 'C');
repaint();
}
/**
*汉诺塔递规调用程序,n是盘子的数量,A,B,C分别代表三个柱子
*/
public void hanio(int n, char A, char B, char C)
{
if(n > 1)
{
hanio(n-1, A, C, B);
pause();//停顿几秒在执行
switch(A)
{
case 'A':adisk[n-1] = 0;break;
case 'B':bdisk[n-1] = 0;break;
case 'C':cdisk[n-1] = 0;break;
default:break;
}
switch(C)
{
case 'A':adisk[n-1] = 1;break;
case 'B':bdisk[n-1] = 1;break;
case 'C':cdisk[n-1] = 1;break;
default:break;
}
repaint();
hanio(n-1, B, A, C);
}
pause();
switch(A)
{
case 'A':adisk[n-1] = 0;break;
case 'B':bdisk[n-1] = 0;break;
case 'C':cdisk[n-1] = 0;break;
default:break;
}
switch(C)
{
case 'A':adisk[n-1] = 1;break;
case 'B':bdisk[n-1] = 1;break;
case 'C':cdisk[n-1] = 1;break;
default:break;
}
repaint();
}
/**
*每隔半妙钟移动一个盘子
*/
public void pause()
{
try{
Thread.sleep(500);//可以修改此值加快盘子移动的速度
}catch(InterruptedException e){}
}
}
分享到:
相关推荐
总的来说,汉诺塔Java实现是一个很好的实践案例,展示了如何使用递归解决复杂问题,以及如何在Java环境中创建简单的用户界面。这个项目可以帮助学习者理解递归算法的工作原理,同时也能提升他们在面向对象编程和GUI...
在Java中实现汉诺塔,通常会用到递归算法,因为问题的本质适合这种解决方式。具体步骤如下: 1. **基础情况**:当汉诺塔只有一个圆盘时,直接将其从起始柱移动到目标柱。 2. **递归步骤**:对于n个圆盘,首先将n-1...
汉诺塔问题是一个经典的递归算法问题,源自印度古老传说,具有很高的教育价值。它涉及到计算机科学中的递归思想、栈数据结构以及问题解决策略。在这个问题中,我们需要将一个包含n个不同大小的圆盘从柱子A移动到柱子...
总结起来,Java实现的汉诺塔问题是一个典型的递归算法应用,它展示了如何通过分解问题并逐步解决来处理复杂任务。理解并实践这个算法有助于提升对递归、函数调用栈以及问题解决策略的理解,这些都是编程中不可或缺的...
在Java中实现汉诺塔的界面,我们可以使用图形用户界面(GUI)库,如Java Swing或JavaFX。Eclipse是一款广泛使用的Java集成开发环境,可以方便地创建和管理这样的项目。 首先,我们需要创建一个Java项目,然后在`src...
汉诺塔问题是一个经典的计算机科学问题,源自印度的古老传说,它涉及...通过学习和实践汉诺塔问题的Java实现,开发者可以提升对递归、分治策略和问题解决能力的理解,这对于编写复杂的算法和解决实际问题具有重要意义。
汉诺塔小游戏
例如,`haniota.java`可能是一个简化版的实现,`tower.java`可能包含了一个类或方法来处理汉诺塔问题,而`TowersOfHanoi.java`可能是主程序,调用了之前定义的`moveTower`方法并设置初始圆盘数进行演示。 理解汉诺...
在Java中实现汉诺塔,主要是通过递归函数来完成。下面我们将详细讨论如何用Java编写汉诺塔的代码,以及涉及的编程概念。 首先,我们需要创建一个`Hanoi`类,它将包含解决汉诺塔问题的主要方法。在这个类中,我们...
总的来说,Java程序设计中的汉诺塔问题不仅展示了递归算法的应用,还涉及了GUI设计、多线程和定时器的使用,这些都是Java开发中非常重要的技能。通过这个玩家游戏,开发者不仅可以锻炼逻辑思维能力,还可以提升GUI...
总的来说,汉诺塔问题的Java实现是学习和掌握递归算法的一个优秀实例,通过理解和编写这样的代码,开发者能够提升解决问题的能力,特别是在处理复杂数据结构和算法设计时。同时,这也是一个很好的练习,有助于提高...
汉诺塔问题是一个经典的递归算法问题,源自印度的一个古老传说。...通过学习汉诺塔问题的Java实现,我们可以更好地理解和掌握递归算法及其在实际问题中的应用,这对于编程和问题解决能力的提升具有重要意义。
在Java编程中解决汉诺塔问题,通常会使用递归函数来实现。这个过程可以分为三个基本步骤: 1. 将A柱上的n-1个圆盘借助B柱移动到C柱。 2. 将A柱剩下的最大圆盘直接移动到C柱。 3. 将B柱上的n-1个圆盘借助A柱移动到C...
在Java编程中,解决汉诺塔问题通常使用递归方法。以下是一个简单的Java代码实现: ```java public class HanoiTower { public static void moveTower(int n, char from, char to, char aux) { if (n > 0) { // ...
这个Java程序不仅实现了汉诺塔问题的解决,还通过Swing构建了一个直观的图形界面来展示解决过程。通过上述分析,我们可以看出该程序涵盖了从问题定义到具体实现的各个方面,非常适合用来教学或学习递归算法及Java ...
汉诺塔问题的Java实现体现了递归的思想,这对于理解和掌握计算机科学中的递归算法至关重要。同时,它也展示了如何通过分治策略解决复杂问题的能力,这是许多高级数据结构和算法的基础。在进行课程设计或项目实践时,...
在本项目中,"汉诺塔 Java版(可实现鼠标拖动和自动演示)",开发者不仅实现了基础的汉诺塔问题的解决方案,还增加了交互性的功能,让用户可以通过鼠标拖动盘子进行操作,这涉及到Java图形用户界面(GUI)的设计。...
汉诺塔的Java实现通常会使用递归算法,递归函数的基本思路是: - 如果只有1个圆盘,直接从起始柱移动到目标柱。 - 对于n个圆盘,首先将上面n-1个圆盘从起始柱通过目标柱移动到辅助柱。 - 然后将第n个圆盘从起始柱...
在Java编程中实现汉诺塔的演示程序,可以帮助理解递归算法和问题解决策略。下面将详细阐述这个Java版汉诺塔演示程序的相关知识点。 1. **汉诺塔问题描述** 汉诺塔问题由三根柱子(A、B、C)和若干个大小不一的圆盘...