java汉诺塔
汉诺塔 java 程序
汉诺塔java 程序import java.awt.*;import java.awt.event.*;import javax.swing.*;public class AutoMoveDisc extends JDialog implements ActionListener{ int amountOfDisc=3;TowerPoint [] pointA,pointB,pointC;char [] towerName;Container con;StringBuffer moveStep;JTextArea showStep;JButton bStart,bStop,bContinue,bClose;Timer time;int i=0,number=0;AutoMoveDisc(Container con){setModal(true);setTitle("自动演示搬盘子过程");this.con=con;moveStep=new StringBuffer();time=new Timer(1000,this);time.setInitialDelay(10);showStep=new JTextArea(10,12);bStart=new JButton("演示");bStop=new JButton("暂停");bContinue=new JButton("继续");bClose=new JButton("关闭");bStart.addActionListener(this);bStop.addActionListener(this);bContinue.addActionListener(this);bClose.addActionListener(this);JPanel south=new JPanel();south.setLayout(new FlowLayout());south.add(bStart);south.add(bStop);south.add(bContinue);south.add(bClose);add(new JScrollPane(showStep),BorderLayout.CENTER);add(south,BorderLayout.SOUTH);setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);towerName=new char[3];addWindowListener(new WindowAdapter(){public void windowClosing(WindowEvent e){time.stop();setVisible(false);}});}public void setPointA(TowerPoint [] pointA){this.pointA=pointA;}public void setPointB(TowerPoint [] pointB){this.pointB=pointB;}public void setPointC(TowerPoint [] pointC){this.pointC=pointC;}public void setTowerName(char name[]){if(name[0]==name[1]||name[0]==name[2]||name[1]==name[2]){towerName[0]='A';towerName[1]='B';towerName[2]='C';}elsetowerName=name;}public void setAmountOfDisc(int n){amountOfDisc=n;}public void actionPerformed(ActionEvent e) {if(e.getSource()==time){number++;char cStart,cEnd;if(i<=moveStep.length()-2){cStart=moveStep.charAt(i);cEnd=moveStep.charAt(i+1);showStep.append("("+number+")从"+cStart+"座搬一个盘子到"+cEnd+"座\n");autoMoveDisc(cStart,cEnd);}i=i+2;if(i>=moveStep.length()-1){time.stop();}}else if(e.getSource()==bStart){if(moveStep.length()==0){if(time.isRunning()==false){i=0;moveStep=new StringBuffer();setMoveStep(amountOfDisc,towerName[0],towerName[1],towerName[2]);number=0;time.start();}}}else if(e.getSource()==bStop){if(time.isRunning()==true)time.stop();}else if(e.getSource()==bContinue){if(time.isRunning()==false)time.restart();}else if(e.getSource()==bClose){time.stop();setVisible(false);}}private void setMoveStep(int amountOfDisc,char one,char two,char three){ if(amountOfDisc==1){moveStep.append(one);moveStep.append(three);}else{setMoveStep(amountOfDisc-1,one,three,two);moveStep.append(one);moveStep.append(three);setMoveStep(amountOfDisc-1,two,one,three);}}private void autoMoveDisc(char cStart,char cEnd){Disc disc=null;if(cStart==towerName[0]){for(int i=0;i<pointA.length;i++){if(pointA[i].isHaveDisc()==true){disc=pointA[i].getDiscOnPoint();pointA[i].setHaveDisc(false);break;}}}if(cStart==towerName[1]){for(int i=0;i<pointB.length;i++){if(pointB[i].isHaveDisc()==true){disc=pointB[i].getDiscOnPoint();pointB[i].setHaveDisc(false);break;}}}if(cStart==towerName[2]){for(int i=0;i<pointC.length;i++){if(pointC[i].isHaveDisc()==true){disc=pointC[i].getDiscOnPoint();pointC[i].setHaveDisc(false);break;}}}TowerPoint endPoint=null;int i=0;if(cEnd==towerName[0]){for(i=0;i<pointA.length;i++){if(pointA[i].isHaveDisc()==true){if(i>0){endPoint=pointA[i-1];break;}else if(i==0)break;}}if(i==pointA.length)endPoint=pointA[pointA.length-1];}if(cEnd==towerName[1]){for(i=0;i<pointB.length;i++){if(pointB[i].isHaveDisc()==true){if(i>0){endPoint=pointB[i-1];break;}else if(i==0)break;}}if(i==pointB.length)endPoint=pointB[pointB.length-1];}if(cEnd==towerName[2]){for(i=0;i<pointC.length;i++){if(pointC[i].isHaveDisc()==true){if(i>0){endPoint=pointC[i-1];break;}else if(i==0)break;}}if(i==pointC.length)endPoint=pointC[pointC.length-1];}if(endPoint!=null&&disc!=null){endPoint.putDisc(disc,con);endPoint.setHaveDisc(true);}}}import javax.swing.*;import java.awt.*;public class Disc extends JButton{int number;TowerPoint point;Disc(){setBackground(Color.cyan);}public void setNumber(int n){number=n;}public int getNumber(){return number;}public void setPoint(TowerPoint p){point=p;}public TowerPoint getPoint(){return point;}}import java.awt.event.*;import java.awt.*;public class HandleMouse implements MouseListener,MouseMotionListener { TowerPoint [] pointA,pointB,pointC;TowerPoint startPoint=null,endPoint=null;int leftX,leftY,x0,y0;boolean move=false,countTime=false;Container con;HandleMouse(Container con){this.con=con;}public void setPointA(TowerPoint [] pointA){this.pointA=pointA;}public void setPointB(TowerPoint [] pointB){this.pointB=pointB;}public void setPointC(TowerPoint [] pointC){this.pointC=pointC;}public void mousePressed(MouseEvent e){move=false;Disc disc=null;disc=(Disc)e.getSource();startPoint=disc.getPoint();x0=e.getX();y0=e.getY();int m=0;for(int i=0;i<pointA.length;i++){if(pointA[i].equals(startPoint)){m=i;if(m>0&&(pointA[m-1].isHaveDisc()==false)){move=true;break;}else if(m==0){move=true;break;}}}for(int i=0;i<pointB.length;i++){if(pointB[i].equals(startPoint)){m=i;if(m>0&&(pointB[m-1].isHaveDisc()==false)){move=true;break;}else if(m==0){move=true;break;}}}for(int i=0;i<pointC.length;i++){if(pointC[i].equals(startPoint)){m=i;if(m>0&&(pointC[m-1].isHaveDisc()==false)){move=true;break;}else if(m==0){move=true;break;}}}}public void mouseMoved(MouseEvent e){}public void mouseDragged(MouseEvent e){Disc disc=null;disc=(Disc)e.getSource();leftX=disc.getBounds().x;leftY=disc.getBounds().y;int x=e.getX();int y=e.getY();leftX=leftX+x;leftY=leftY+y;if(move==true)disc.setLocation(leftX-x0,leftY-y0);}public void mouseReleased(MouseEvent e){Disc disc=null;disc=(Disc)e.getSource();Rectangle rect=disc.getBounds();boolean location=false;int x=-1,y=-1;for(int i=0;i<pointA.length;i++){x=pointA[i].getX();y=pointA[i].getY();if(rect.contains(x,y)){endPoint=pointA[i];if(i==pointA.length-1&&endPoint.isHaveDisc()==false){location=true;break;}else if(i<pointA.length-1&&pointA[i+1].isHaveDisc()==true&&endPoint.isHaveDisc()==false&&pointA[i+1].getDiscOnPoint().getNumber()>disc.getNumber()){location=true;break;}}}for(int i=0;i<pointB.length;i++){x=pointB[i].getX();y=pointB[i].getY();if(rect.contains(x,y)){endPoint=pointB[i];if(i==pointB.length-1&&endPoint.isHaveDisc()==false){location=true;break;}else if(i<pointB.length-1&&pointB[i+1].isHaveDisc()==true&&endPoint.isHaveDisc()==false&&pointB[i+1].getDiscOnPoint().getNumber()>disc.getNumber()){location=true;break;}}}for(int i=0;i<pointC.length;i++){x=pointC[i].getX();y=pointC[i].getY();if(rect.contains(x,y)){endPoint=pointC[i];if(i==pointC.length-1&&endPoint.isHaveDisc()==false){location=true;break;}else if(i<pointC.length-1&&pointC[i+1].isHaveDisc()==true&&endPoint.isHaveDisc()==false&&pointC[i+1].getDiscOnPoint().getNumber()>disc.getNumber()){location=true;break;}}}if(endPoint!=null&&location==true){endPoint.putDisc(disc,con);startPoint.setHaveDisc(false);}elsestartPoint.putDisc(disc,con);}public void mouseEntered(MouseEvent e){}public void mouseExited(MouseEvent e){}public void mouseClicked(MouseEvent e){}}import javax.swing.*;import java.awt.*;import java.awt.event.*;public class HannoiWindow extends JFrame implements ActionListener{ Tower tower=null;int amountOfDisc=3;char []towerName={'A','B','C'};JMenuBar bar;JMenu menuGrade;JMenuItem oneGradeItem,twoGradeItem,threeGradeItem;JButton renew=null;JButton autoButton=null;JPanel center=new JPanel();HannoiWindow(){tower=new Tower(towerName);tower.setAmountOfDisc(amountOfDisc);tower.setMaxDiscWidth(120);tower.setMinDiscWidth(50);tower.setDiscHeight(16);tower.putDiscOnTower();add(tower,BorderLayout.CENTER);bar=new JMenuBar();menuGrade=new JMenu("选择级别");oneGradeItem=new JMenuItem("初级");twoGradeItem=new JMenuItem("中级");threeGradeItem=new JMenuItem("高级");menuGrade.add(oneGradeItem);menuGrade.add(twoGradeItem);menuGrade.add(threeGradeItem);bar.add(menuGrade);setJMenuBar(bar);oneGradeItem.addActionListener(this);twoGradeItem.addActionListener(this);threeGradeItem.addActionListener(this);renew=new JButton("重新开始");renew.addActionListener(this);autoButton=new JButton("自动演示");autoButton.addActionListener(this);JPanel north=new JPanel();north.add(renew);north.add(autoButton);String mess="将全部盘子从"+towerName[0]+"座搬运到"+towerName[1]+ "座或"+towerName[2]+"座";JLabel hintMess=new JLabel(mess,JLabel.CENTER);north.add(hintMess);add(north,BorderLayout.NORTH);setResizable(false);setVisible(true);setBounds(60,60,460,410);validate();setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);}public void actionPerformed(ActionEvent e){if(e.getSource()==oneGradeItem){amountOfDisc=3;tower.setAmountOfDisc(amountOfDisc);tower.putDiscOnTower();}else if(e.getSource()==twoGradeItem){amountOfDisc=4;tower.setAmountOfDisc(amountOfDisc);tower.putDiscOnTower();}else if(e.getSource()==threeGradeItem){amountOfDisc=5;tower.setAmountOfDisc(amountOfDisc);tower.putDiscOnTower();}else if(e.getSource()==renew){tower.setAmountOfDisc(amountOfDisc);tower.putDiscOnTower();}else if(e.getSource()==autoButton){tower.setAmountOfDisc(amountOfDisc);tower.putDiscOnTower();int x=this.getBounds().x+this.getBounds().width;int y=this.getBounds().y;tower.getAutoMoveDisc().setLocation(x,y);tower.getAutoMoveDisc().setSize(280,this.getBounds().height);tower.getAutoMoveDisc().setVisible(true);}validate();}public static void main(String args[]){new HannoiWindow();}}import javax.swing.*;import java.awt.*;public class Tower extends JPanel{int amountOfDisc=3;Disc [] disc;int maxDiscWidth,minDiscWidth,discHeight;char [] towerName;TowerPoint [] pointA,pointB,pointC;HandleMouse handleMouse;AutoMoveDisc autoMoveDisc;Tower(char [] towerName){handleMouse=new HandleMouse(this);this.towerName=towerName;setLayout(null);setBackground(new Color(200,226,226));}public void setAmountOfDisc(int number){if(number<=1)amountOfDisc=1;elseamountOfDisc=number;}public void setMaxDiscWidth(int m){maxDiscWidth=m;}public void setMinDiscWidth(int m){minDiscWidth=m;}public void setDiscHeight(int h){discHeight=h;}public AutoMoveDisc getAutoMoveDisc(){return autoMoveDisc;}public void putDiscOnTower(){removeDisk();int n=(maxDiscWidth-minDiscWidth)/amountOfDisc;disc=new Disc[amountOfDisc];for(int i=0;i<disc.length;i++){disc[i]=new Disc();disc[i].setNumber(i);int diskwidth=minDiscWidth+i*n;disc[i].setSize(diskwidth,discHeight);disc[i].addMouseListener(handleMouse);disc[i].addMouseMotionListener(handleMouse);}pointA=new TowerPoint[amountOfDisc];pointB=new TowerPoint[amountOfDisc];pointC=new TowerPoint[amountOfDisc];int vertialDistance=discHeight;for(ii<pointA.nt i=0;length;i++){pointA[i]=new TowerPoint(maxDiscWidth,100+vertialDistance);vertialDistance=vertialDistance+discHeight;}vertialDistance=discHeight;for(int i=0;i<pointB.length;i++){pointB[i]=new TowerPoint(2*maxDiscWidth,100+vertialDistance);vertialDistance=vertialDistance+discHeight;}vertialDistance=discHeight;for(int i=0;i<pointC.length;i++){pointC[i]=new TowerPoint(3*maxDiscWidth,100+vertialDistance);vertialDistance=vertialDistance+discHeight;}for(int i=0;i<pointA.length;i++){pointA[i].putDisc(disc[i],this);}handleMouse.setPointA(pointA);handleMouse.setPointB(pointB);handleMouse.setPointC(pointC);autoMoveDisc=new AutoMoveDisc(this);autoMoveDisc.setTowerName(towerName);autoMoveDisc.setAmountOfDisc(amountOfDisc);autoMoveDisc.setPointA(pointA);autoMoveDisc.setPointB(pointB);autoMoveDisc.setPointC(pointC);validate();repaint();}public void removeDisk(){if(pointA!=null){for(int i=0;i<pointA.length;i++){pointA[i].removeDisc(pointA[i].getDiscOnPoint(),this);pointB[i].removeDisc(pointB[i].getDiscOnPoint(),this);pointC[i].removeDisc(pointC[i].getDiscOnPoint(),this);}}}public void paintComponent(Graphics g){super.paintComponent(g);int x1,y1,x2,y2;x1=pointA[0].getX();y1=pointA[0].getY()-discHeight/2;x2=pointA[amountOfDisc-1].getX();y2=pointA[amountOfDisc-1].getY()+discHeight/2;g.drawLine(x1,y1,x2,y2);x1=pointB[0].getX();y1=pointB[0].getY()-discHeight/2;x2=pointB[amountOfDisc-1].getX();y2=pointB[amountOfDisc-1].getY()+discHeight/2;g.drawLine(x1,y1,x2,y2);x1=pointC[0].getX();y1=pointC[0].getY()-discHeight/2;x2=pointC[amountOfDisc-1].getX();y2=pointC[amountOfDisc-1].getY()+discHeight/2;g.drawLine(x1,y1,x2,y2);g.setColor(Color.blue);x1=pointA[amountOfDisc-1].getX()-maxDiscWidth/2;y1=pointA[amountOfDisc-1].getY()+discHeight/2;x2=pointC[amountOfDisc-1].getX()+maxDiscWidth/2;y2=pointC[amountOfDisc-1].getY()+discHeight/2;int length=x2-x1,height=6;g.fillRect(x1,y1,length,height);int size=5;for(int i=0;i<pointA.length;i++){g.fillOval(pointA[i].getX()-size/2,pointA[i].getY()-size/2,size,size);g.fillOval(pointB[i].getX()-size/2,pointB[i].getY()-size/2,size,size);g.fillOval(pointC[i].getX()-size/2,pointC[i].getY()-size/2,size,size);}g.drawString(towerName[0]+"座",pointA[amountOfDisc-1].getX(),pointA[amountOfDisc-1].getY()+50);g.drawString(towerName[1]+"座",pointB[amountOfDisc-1].getX(),pointB[amountOfDisc-1].getY()+50);g.drawString(towerName[2]+"座",pointC[amountOfDisc-1].getX(),pointC[amountOfDisc-1].getY()+50);}}import java.awt.*;public class TowerPoint{int x,y;boolean haveDisc;Disc disc=null;public TowerPoint(int x,int y){this.x=x;this.y=y;}public boolean isHaveDisc(){return haveDisc;}public void setHaveDisc(boolean boo){haveDisc=boo;}public int getX(){return x;}public int getY(){return y;}public boolean equals(TowerPoint p){if(p.getX()==this.getX()&&p.getY()==this.getY())return true;elsereturn false;}public void putDisc(Component com,Container con){ disc=(Disc)com;con.setLayout(null);con.add(disc);int w=disc.getBounds().width;int h=disc.getBounds().height;disc.setBounds(x-w/2,y-h/2,w,h);haveDisc=true;disc.setPoint(this);con.validate();}public Disc getDiscOnPoint(){return disc;}public void removeDisc(Component com,Container con){ if(com!=null)con.remove(com);con.validate();}}。
java汉诺塔详解及实现代码
java汉诺塔详解及实现代码java 汉诺塔详解及实现代码实现效果图打印的⽅法在 moveTheTopOne() ⽅法中被调⽤,调⽤该⽅法前打印出移动的⽅向--从X号塔往Y号塔汉诺塔要求:将第⼀座塔上的所有盘⼦,借助第⼆座塔,全部搬运到第三座塔上。
规则:⼀次只能搬运⼀个盘⼦,不准将⼤盘⼦落在⼩盘⼦上。
汉诺塔实现代码: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>();// 映射,⽤来确定并打印塔的序号(使⽤⾓标),也可以使⽤ Mapprivate 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;}// 将实现分为三步,⼀,将源塔底盘上⽅的所有盘⼦移⾄中间塔(递归);⼆,将底盘移到⽬标塔;三,将中间塔上的所有盘⼦移到⽬标塔上(递归)。
汉诺塔问题的详解课件
04
数据结构与排序
汉诺塔问题也可以用来解释和演示不同的 数据结构和排序算法。
05
06
通过汉诺塔问题,人们可以更好地理解如 堆、栈等数据结构的应用和优劣。
在物理学中的应用
复杂系统与自组织
汉诺塔问题在物理学中常被用来研究复杂系统和自组织现 象。
通过对汉诺塔问题的深入研究,人们可以发现其在物理学 中的一些应用,如量子计算、自旋玻璃等。
人工智能与机器学习
在人工智能和机器学习中,汉诺塔问题可以被用来演示 如何使用不同的算法来解决问题。
06
总结与展望
对汉诺塔问题的总结
汉诺塔问题是一个经典的递归问题,其核心在于将一个复杂的问题分解为若干个简单的子问题来解决 。
通过解决汉诺塔问题,我们可以了解到递归算法在解决复杂问题中的重要性,以及将大问题分解为小问 题的方法。
此外,汉诺塔问题还被广泛应用于数学教育和计算机 科学教育中,成为许多课程和教材中的经典案例之一
。
02
汉诺塔问题的数学模型
建立数学模型
定义问题的基本参数
盘子的数量、柱子的数量和塔的直径 。
建立数学方程
根据问题的特点,我们可以建立如下 的数学方程。
递归算法原理
递归的基本思想
将一个复杂的问题分解成更小的子问题来解决。
通过深入研究汉诺塔问题的本质和解决方法,我们可以 为解决其他领域的问题提供有益的启示和方法。
THANKS
感谢观看
其他移动规则
除了传统的规则(盘子只能放在更大的盘子下面)之外,还 可以有其他移动规则,这会改变问题的性质和解决方案。
05
汉诺塔问题的应用场景
在计算机科学中的应用
算法设计与优化
01
汉诺塔代码java实现
汉诺塔代码java实现汉诺塔(Tower of Hanoi)是一种经典的数学问题和递归算法示例。
这个问题的目标是将一堆盘子从一个柱子上移动到另一个柱子上,同时遵守以下规则:只能移动一个盘子,移动过程中不能将较大的盘子放在较小的盘子上。
以下是使用Java语言实现汉诺塔问题的代码示例:```javapublic class HanoiTower {public static void move(int n, char source, char target, char auxiliary) {if (n == 1) {System.out.println("Move disk 1 from " + source + " to " + target);return;}move(n - 1, source, auxiliary, target);System.out.println("Move disk " + n + " from " + source + " to " + target);move(n - 1, auxiliary, target, source);}public static void main(String[] args) {int n = 3; // 盘子的个数move(n, 'A', 'C', 'B');}}```在上述代码中,我们定义了一个名为`move`的递归函数,该函数接受四个参数:盘子的数量`n`、源柱子`source`、目标柱子`target`和辅助柱子`auxiliary`。
递归函数的作用是将`n`个盘子从源柱子移动到目标柱子。
当`n`等于1时,表示只有一个盘子需要移动,此时直接将该盘子从源柱子移动到目标柱子即可。
当`n`大于1时,我们需要先将`n-1`个盘子从源柱子移动到辅助柱子,然后将第`n`个盘子从源柱子移动到目标柱子,最后再将`n-1`个盘子从辅助柱子移动到目标柱子。
java实现汉诺塔详解及实现代码
java实现汉诺塔详解及实现代码java 实现汉诺塔详解及实现代码汉诺塔问题:有三根柱⼦A,B,C,其中A上⾯有n个圆盘,从上⾄下圆盘逐渐增⼤,每次只能移动⼀个圆盘,并且规定⼤的圆盘不能叠放在⼩的圆盘上⾯,现在想要把A上⾯的n个圆盘全部都移动到C上⾯,输出移动的总步数以及移动的过程分析://先求出移动的总步数1,假设g(n)表⽰n个圆盘时的移动总的步数,当n=1时,g(1)=1;2.现在可以把g(n)进⾏细分为三步:1>先将n-1个圆盘从A通过C移动到B上⾯,相当于将n-1个圆盘从A移动到C,因此需要g(n-1)步;2>然后将剩下的最⼤的圆盘从A移动到C,需要1步;3>最后再将n-1个圆盘从B通过A移动到C上⾯,相当于将n-1个圆盘从A移动到C,因此也需要g(n-1)步;因此可以得出递归关系式:g(n) = 2*g(n-1)+1;//现在我们在来求出移动的过程1.假设hm(m,a,b,c)表⽰将m个圆盘从a通过b移动到c的过程,假设mv(a,c)输出⼀次a到c的过程,即print a-->c2.初始化hm,当m=1时,hm(1,a,b,c)=mv(a,c);2.可以把hm(m,a,b,c)进⾏细分为三步:1>先将n-1个圆盘从A通过C移动到B,此时b和c进⾏互换,也就是 hm(m-1,a,c,b);2>然后将剩下的最⼤的圆盘从A移动到C,也就是hm(1,a,b,c);3>最后将n-1个圆盘从B通过A移动到C,此时b和a进⾏交换,也就是 hm(m-1,b,a,c);最终得到过程的递归关系式:hm(m,a,b,c) = hm(m-1,a,c,b)+1+hm(m-1,b,a,c);实现代码:public class test{public static void main(String[] args){Scanner in = new Scanner(System.in);int n = in.nextInt();test t = new test();//获取总的步数System.out.println("需要移动的总步数为:" +t.getSum(n));//获取移动的过程t.hm(n,'a','b','c');}//获取总步数public int getSum(int n){if(n == 1)return 1;return 2 * getSum(n-1) +1 ;}//获取移动的过程public void hm(int m,char a,char b,char c){if(m == 1)move(a,c);hm(m-1,a,c,b);move(a,c);hm(m-1,b,a,c);}//输出⼀次移动的过程public void move(char a,char c){System.out.print(a + "-->" + c + " ");}}感谢阅读,希望能帮助到⼤家,谢谢⼤家对本站的⽀持!。
Java陷阱之assert关键字详解
Java陷阱之assert关键字详解在C和C++语⾔中都有assert关键,表⽰断⾔。
在Java中,同样也有assert关键字,表⽰断⾔,⽤法和含义都差不多。
在Java中,assert关键字是从JAVA SE 1.4 引⼊的,为了避免和⽼版本的Java代码中使⽤了assert关键字导致错误,Java在执⾏的时候默认是不启动断⾔检查的(这个时候,所有的断⾔语句都将忽略!),如果要开启断⾔检查,则需要⽤开关-enableassertions或-ea来开启。
assert关键字语法很简单,有两种⽤法:1、assert <boolean表达式>如果<boolean表达式>为true,则程序继续执⾏。
如果为false,则程序抛出AssertionError,并终⽌执⾏。
2、assert <boolean表达式> : <错误信息表达式>如果<boolean表达式>为true,则程序继续执⾏。
如果为false,则程序抛出ng.AssertionError,并输⼊<错误信息表达式>。
下⾯给出⼀个例⼦,通过例⼦说明其⽤法:复制代码代码如下:public class AssertFoo {public static void main(String args[]) {//断⾔1结果为true,则继续往下执⾏assert true;System.out.println("断⾔1没有问题,Go!");System.out.println("\n-----------------\n");//断⾔2结果为false,程序终⽌assert false : "断⾔失败,此表达式的信息将会在抛出异常的时候输出!";System.out.println("断⾔2没有问题,Go!");}}保存代码到C:\AssertFoo.java,然后按照下⾯的⽅式执⾏,查看控制台输出结果:C:\>javac AssertFoo.javaC:\>java AssertFoo断⾔1没有问题,Go!-----------------断⾔2没有问题,Go!C:\>java -ea AssertFoo断⾔1没有问题,Go!-----------------Exception in thread "main" ng.AssertionError: 断⾔失败,此表达式的信息将会在抛出异常的时候输出!at AssertFoo.main(AssertFoo.java:10)assert关键字⽤法简单,但是使⽤assert往往会让你陷⼊越来越深的陷阱中。
java递归算法经典题目
java递归算法经典题目递归是一种常见的算法思想,它通过将问题分解为更小的子问题来解决问题。
在Java中,递归算法可以用于解决许多经典问题,如斐波那契数列、汉诺塔、阶乘等。
下面我们将介绍一些Java递归算法经典题目,帮助您更好地理解和掌握递归算法。
1.斐波那契数列斐波那契数列是一个经典的递归问题,它是指从第0项开始,每一项都是前两项的和。
在Java中,可以使用递归方法来求解斐波那契数列。
以下是一个简单的递归算法实现:```javapublicstaticintfibonacci(intn){if(n<=1){returnn;}else{returnfibonacci(n-1)+fibonacci(n-2);}}```这个算法会一直递归调用直到达到斐波那契数列的末项为止。
需要注意的是,递归算法的时间复杂度较高,当n值较大时可能会导致栈溢出等问题。
2.汉诺塔问题汉诺塔问题是一个经典的递归问题,它描述了一个操作:将一堆盘子从一个柱子移动到另一个柱子,要求遵循以下规则:每次只能移动一个盘子,并且大盘子不能放在小盘子上面。
在Java中,可以使用递归方法来解决汉诺塔问题。
以下是一个简单的递归算法实现:```javapublicstaticvoidhanoi(intn,Stringfrom,Stringto,Stringvia) {if(n==1){System.out.println("Movedisk"+n+"from"+from+"to"+to);}else{hanoi(n-1,from,via,to);System.out.println("Movedisk1from"+from+"to"+to);hanoi(n-1,via,to,from);}}```这个算法会一直递归调用,直到完成所有盘子的移动。
Hannoi塔(汉诺塔)--Java课程设计报告
Java课程设计报告题目汉诺塔所在院系软件学院学生姓名邓小文专业土木+软件工程班级08-1班学号14号2010年7月17日一、总体设计1.本系统的主要功能(1)本软件是汉诺塔游戏;(2)可以实现计时功能;(3)游戏结束时记录排名;(4)在玩游戏的同时还可以欣赏歌曲;(5)不知如何玩时可以实现自动演示;2.系统包含的类及类之间的关系为了实现本软件的各项功能,对要在本软件中需要用到的源文件进行总体设计。
本系统共包括12个java 源文件。
1.各个类之间的关系如图1所示。
Hel TowerHannoiTower Musi Disk TowerPoint TimeRecord ShowRecor Peopl图1-1各个类之间的关系2.java 源文件及其功能,如表所示。
表1java 源文件及其功能二、详细设计为了实现总体设计中的各个类之间的接口连接,使玩家能够顺畅的使用本软件进行游戏,考虑用详细设计来给玩家一一介绍。
以下是对本软件的详细设计:序号文件名主要功能备注1Tower 用户可以在主窗口选择开始搬运盘子或自动演示。
程序默认的情况是手动搬运盘子2HannoiTower 该文件生成的类负责创建Hannoi塔,汉诺塔由A、B、C 三个塔组成,可以用鼠标搬运各个塔上的盘子。
3Disk该文件生成的类负责创建盘子对象4TowerPoint 该文件生成的类负责为Hannoi 塔创建塔点对象,即盘子放置的位置。
5Time 记录玩家完成游戏所需的时间6People 记录成绩能够排进排行榜的选手7About 关与本软件的制作信息8Help 帮助主题9Record 记录10Music 该文件负责生成一款播放器,可以选取玩家自己喜欢的歌曲欣赏。
播放的歌曲需要是“wav”等形式的。
11ShowRecord该文件用来实现玩家看英雄榜的情况。
1.主类Tower(1)该类用到的主要成员变量见表5表5类Tower主要成员变量成员变量描述变量类型名称汉诺塔对象HannoiTower tower塔名数组Char[]TowerName盘子数目int盘子数目p float盘子从上到下缩小的比例盘子大小Int盘宽,盘高自动演示线程Thread Threadfile初级,file高级File初级高级排行榜记录file1,file2File规则帮助文本自动演示文字显示搬运过程TextArea信息条背景音乐Music music菜单条JMenuBar bar菜单JMenu fileMenu1,fileMenu2,fileMenu3菜单项JMenuItem 开始游戏,重新开始,自动演示,英雄榜,退出,背景音乐,帮助主题,关于汉诺塔;显示时间JTextField显示时间(2)方法见表6表6类Tower主要方法名称功能备注Tower创建窗口构造方法(3)源代码见文件Tower.java2.类HannoiTower(1)该类用到的主要成员变量见表7表7类HannoiTower主要成员变量成员变量描述变量类型变量名位置int X,Yp float盘子从上到下缩小的比例搬运坐标int Shartx,Starty,Starti盘子数目int盘子数目塔名char Towername[]时间int spendtime塔点TowerPoint point[]移动状态boolean move盘子Disk盘子[]显示移动信息TextArea信息条用来计时Time计时计时器是否启动boolean计时器是否启动(2)方法见表8表8类HannoiTower主要方法名称功能(3)源代码见文件HannoiTower.java3.类TowerPoint(1)该类用到的主要成员变量见表9表9类TowerPoint主要成员变量成员变量描述变量类型变量名位置Int X,Yboolean有盘子查看是否有盘子创建盘子Disk盘子创建塔HannoiTower con (2)方法见表10表10类TowerPoint主要方法名称功能是否有盘子返回“有盘子”变量的状态(3)源代码见文件TowerPoint.java4.类Disk(1)该类用到的主要成员变量见表11表11类Disk主要成员变量成员变量描述变量类型变量名数目int number 上方有无盘子boolean上方有盘(2)方法见表12表12类Disk主要方法名称功能get上方有盘得到“上方有盘”set上方有盘设置“上方有盘”getNumber得到盘子号(3)源代码见文件Disk.java5.类Time(1)该类用到的主要成员变量见表13表13类Time主要成员变量成员变量描述变量类型变量名时间int time计时器javax.swing.Timer计时器显示时间JTextField显示时间计时器是否启动boolean计时器是否启动(2)方法见表14表14类Time主要方法名称功能actionPerformed处理ActionEvent事件begin设置开始计时rebegin设置重新开始计时pause设置停止计时clear设置计时清零且不显示(3)源代码见文件Time.java6.类Music(1)该类用到的主要成员变量见表15表15类Music主要成员变量成员变量描述变量类型变量名线程Thread thread音频对象AudioClip clip按钮Button buttonPlay,buttonLoop,buttonStop选择框Choice choice面板Panel p1,p2盒式容器Box baseBox,boxV1,boxV2标签Label标签1,标签2(2)方法见表16表16类Music主要方法名称功能Music创建背景音乐对话框run启动线程actionPerformed处理ActionEvent事件(3)源代码见文件Music.java7.类People(1)该类用到的主要成员变量见表17表17类People主要成员变量成员变量描述变量类型变量名测试者姓名String name测试所用时间int time(2)方法见表18表18类People主要方法名称功能People获取测试者姓名getTime获取测试所用时间(3)源代码见文件People.java8.类Record(1)该类用到的主要成员变量见表19表19类Record主要成员变量变量类型变量名功能int time记录游戏所用时间int n判断级别JTextFile yourName记录测试者的名字File gradeFile存放成绩的文件JButton确定,取消是否保存成绩的按钮(2)方法见表20表20类Record主要方法名称功能Record创建保存成绩窗口setTime设置时间setFile设置文件actionPerformed处理ActionEvent事件(3)源代码见文件Record.java9.类ShowRecord(1)该类用到的主要成员变量见表21表21类ShowRecord主要成员变量变量类型变量名功能File gradeFile存放成绩的文件JButton确定,清除按钮JTextArea Show显示成绩的区域(2)方法见表22表22类ShowRecord主要方法名称功能ShowRecord创建显示成绩窗口actionPerformed处理ActionEvent事件(3)源代码见文件ShowRecord.java10.类Help(1)该类用到的主要成员变量见表25表25类Help主要成员变量变量类型变量名功能TextArea text存放帮助主题的文件FileReader f帮助主题的文本文档(2)方法见表26表26类Help主要方法名称功能Help创建帮助窗口三、运行效果1、将10个java文件打包保存到同一个文件夹中,并且分别编译生成相应的字节码文件。
汉诺塔问题
汉诺塔百科名片汉诺塔初始状态汉诺塔:汉诺塔(又称河内塔)问题是源于印度一个古老传说的益智玩具。
上帝创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上安大小顺序摞着64片黄金圆盘。
上帝命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。
并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。
目录由来汉诺塔与宇宙寿命concreteHAM:汉诺塔问题的程序实现由来汉诺塔与宇宙寿命concreteHAM:汉诺塔问题的程序实现展开编辑本段由来来源汉诺塔是源自印度神话里的玩具。
上帝创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按大小顺序摞着64片黄金圆盘。
上帝命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。
并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。
传说在印度,有这么一个古老的传说:在世界中心贝拿勒斯(在印度北部)的圣庙里,一块黄铜板上插着三根宝石针。
印度教的主神梵天在创造世界的时候,在其中一根针上从下到上地穿好了由大到小的64片金片,这就是所谓的汉诺塔。
不论白天黑夜,总有一个僧侣在按照下面的法则移动这些金片:一次只移动一片,不管在哪根针上,小片必须在大片上面。
僧侣们预言,当所有的金片都从梵天穿好的那根针上移到另外一根针上时,世界就将在一声霹雳中消灭,而梵塔、庙宇和众生也都将同归于尽。
不管这个传说的可信度有多大,如果考虑一下把64片金片,由一根针上移到另一根针上,并且始终保持上小下大的顺序。
这需要多少次移动呢?这里需要递归的方法。
假设有n片,移动次数是f(n).显然f(1)=1,f(2)=3,f(3)=7,且f(k+1)=2*f(k)+1。
此后不难证明f(n)=2^n-1。
n=64时,f(64)= 2^64-1=18446744073709551615假如每秒钟一次,共需多长时间呢?一个平年365天有31536000 秒,闰年366天有31622400秒,平均每年31556952秒,计算一下,18446744073709551615/31556952=584554049253.855年这表明移完这些金片需要5845亿年以上,而地球存在至今不过45亿年,太阳系的预期寿命据说也就是数百亿年。
汉诺塔
《JA V A语言程序设计》课程设计题目:汉诺塔随着计算机的普及越来越多得人使用计算机,人们得生活工作越来越离不开计算机!但是人们面对长时间的电脑工作,难免会有厌倦情绪,而现代人使用最多得打发无聊时间得方式,多是:聊天,浏览网页,看电影,玩大型得网游,结果到头来,花费勒很多得时间却发现自己并没有放松,相反还使自己更加精力疲倦!汉诺塔是一款益智小游戏,花费得时间不多,但是你却要经过思考来完成,从而获得身心得放松!关键词:汉诺塔;计算机;游戏;演示;移动1.引言 (1)1.1问题的提出 (1)1.2 任务设计内容 (1)2.需求分析 (2)2.1 界面及布局设计 (2)2.2 A、B、C 座的实现方法 (2)2.3 圆盘的实现方法 (3)2.4 记录时间方法 (3)3.总体设计 (4)3.1总体功能图 (4)3.2总体流程图 (5)4.主要功能设计流程 (6)4.1 A、B、C 座实现流程图 (6)4.2圆盘画法流程图 (7)4.3保存流程图 (7)4.4时间流程图 (8)5.代码实现 (8)5.1间关系图 (8)5.2 运行效果图 (9)6.总结与说明 (10)7.负责的部分原代码 (11)8.参考文献 (23)1.引言1.1问题的提出随着计算机得普及,人们越来越多得接触到计算机,人们得生活工作中无处不有计算机得身影!人们面对长时间的难免会有倦怠的情绪!而人们大多得缓解情绪得网络活动其实并不能起到放松心情得作用!现代人得生活节奏越来越快,有没有一种快速缓解疲倦得游戏呢?我们提出设计一款益智得小游戏,这种游戏不会花太多时间,同时把玩家得思维带动起来,达到一举多得得效果!1.2 任务设计内容(1)设计Hannoi塔中有三个座,名字分别是A、B和C。
初始状态是A座上有3个大小不等的盘子,这些盘子从座底到座顶按着大小顺序依次摆放在A 座上。
用户可以用鼠标选中盘子,然后通过拖动鼠标来移动该盘子、释放鼠标来放置该盘子;(2)程序要求用户在移动盘子过程中,不允许把大盘放置在小盘的上面,用户最终要完成的是把A座上的全部盘子移动到B座或C座上;(3)用户可以通过Hannoi塔界面提供的菜单来选择初级、中级、高级和自定义四个级别。
汉诺塔游戏java编程
辽宁工业大学JA V A语言程序设计课程设计(论文)题目:汉诺塔游戏设计院(系):软件学院专业班级:计算机网络技术091班学号:091406015学生姓名:张铎赢指导教师:赵凯教师职称:讲师起止时间:2010.12.13至2010.12.24程序设计专题(报告)任务及评语目录第1章课程设计的目的与要求 (1)1.1 课程设计目的 (1)1.2 课程设计的实验环境 (1)1.3 课程设计的预备知识 (1)1.4 课程设计要求 (1)第2章课程设计内容 (2)2.1课程设计主要内容 (2)2.2概要设计 (2)2.2.1自定义类说明 (2)2.3详细设计 (3)2.4.1程序运行情况 (13)2.4.2程序异常处理 (16)第3章课程设计总结 (17)附录参考资料.................................................................第1章课程设计的目的与要求1.1 课程设计目的《JA V A程序设计》是计算机相关专业的必修专业基础课程,其实践性、应用性很强。
实践教学环节是必不可少的一个重要环节。
本课程的程序设计专题实际是计算机相关专业学生学习完《JA V A程序设计》课程后,进行的一次全面的综合训练,JA V A程序设计的设计目的是加深对理论教学内容的理解和掌握,使学生较系统地掌握程序设计及其在网络开发中的广泛应用,基本方法及技巧,为学生综合运用所学知识,利用软件工程为基础进行软件开发、并在实践应用方面打下一定基础。
1.2 课程设计的实验环境硬件要求能运行Windows 9.X操作系统的微机系统。
JA V A程序设计语言及相应的集成开发环境,J2SDK和ECLIPSE开发工具。
1.3 课程设计的预备知识熟悉JA V A语言及ECLIPSE开发工具。
1.4 课程设计要求按课程设计指导书提供的课题,要求学生在自行完成各个操作环节,并能实现且达到举一反三的目的,完成一个项目解决一类问题。
Java实现汉诺塔游戏(可打印修改)
/** * 记录盘子的初始坐标 */ int startX, startY;
/** * 记录盘子的初始塔点 */ int startI;
/** * 盘的总数 */ int totalDisk;
/** * 最大号盘子的宽和高 */ int width, height;
hasDiskUpstairs = b; }
/** * 获取当前盘的编号 * @return */ public int getNumber() {
return number; } }
//游戏配置类 GameConfig.java
package towers;
public class GameConfig {
setLayout(null); setBackground(Color.cyan); addMouseListener(this);
//创建盘组 diskArray = new Disk[this.totalDisk]; point = new TowerPoint[3 * this.totalDisk];
int diskHeight = 20; // 给出 A 塔中塔点坐标 for (int i = 0; i < this.totalDisk; i++) {
point[i] = new TowerPoint(2 * width, 100 + diskHeight, false); diskHeight = diskHeight + height; }
int tempWidth = width; int sub = (int) (tempWidth / this.totalDisk );
java中递归例子
java中递归例子递归是一种在编程中常用的技巧,它可以通过调用自身来解决问题。
在Java中,递归可以应用于各种问题,从简单的数学运算到复杂的数据结构操作。
下面将列举10个不同的Java递归例子,每个例子都将详细介绍递归的原理和实现方式。
1. 阶乘计算阶乘是一个常见的数学运算,表示从1到给定数字n的连续乘积。
递归可以用来计算阶乘,通过将问题分解为更小的子问题,最终得到结果。
例如,计算5的阶乘可以表示为:5! = 5 * 4 * 3 * 2 * 1。
2. 斐波那契数列斐波那契数列是一个经典的递归问题,其中每个数字是前两个数字之和。
例如,斐波那契数列的前几个数字是:0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ...3. 数组求和递归可以用来计算数组中所有元素的和。
通过将数组分解为更小的子数组,并将每个子数组的和累加起来,我们可以得到整个数组的总和。
4. 数组反转递归可以用来反转一个数组。
通过将数组的第一个元素与最后一个元素交换,并递归地对剩余的子数组进行反转,我们可以得到整个数组的反转结果。
5. 链表反转递归可以用来反转一个链表。
通过将链表的头节点与剩余的子链表进行反转,并将头节点的next指针指向已反转的子链表的末尾,我们可以得到整个链表的反转结果。
6. 树的遍历递归可以用来实现树的遍历算法,包括前序遍历、中序遍历和后序遍历。
通过递归地遍历树的左子树和右子树,我们可以按照指定的顺序访问树的所有节点。
7. 字符串反转递归可以用来反转一个字符串。
通过将字符串的第一个字符与最后一个字符交换,并递归地对剩余的子字符串进行反转,我们可以得到整个字符串的反转结果。
8. 汉诺塔问题汉诺塔问题是一个经典的递归问题,其中有三个柱子和一组圆盘,圆盘按照从小到大的顺序堆叠在柱子上。
目标是将所有圆盘从一个柱子移动到另一个柱子,同时遵循以下规则:每次只能移动一个圆盘,大圆盘不能叠在小圆盘上。
9. 排列组合递归可以用来生成给定集合的所有排列或组合。
java 图形界面程序,汉诺塔演示程序代码
package .hanoi;import java.awt.*;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.awt.event.WindowAdapter;import java.awt.event.WindowEvent;import javax.swing.JDialog;import javax.swing.JLabel;import javax.swing.JPanel;class Desk extends Panel{Label topPanel,leftLeg,rightLeg,name;int num; // 桌子上现有盘子的数量public int topy=340,topx=80; //第一个个盘子在哪里放下int maxsize=12;int initialx=0,initialy=340;int record[]=new int[12];Desk(String s) //构造函数{name=new Label();name.setText(s); //桌子名称topPanel=new Label();topPanel.setBackground(Color.red);leftLeg=new Label();rightLeg=new Label();this.setSize(180, 160); //桌子面板大小this.setLayout(null);this.add(topPanel);this.add(leftLeg);this.add(rightLeg);this.add(name);this.setFont(new Font("宋体",Font.CENTER_BASELINE, 16));this.setForeground(Color.blue);topPanel.setBounds(10, 0,160, 30);leftLeg.setBackground(Color.red);leftLeg.setBounds(35,30,30,50);rightLeg.setBackground(Color.red);rightLeg.setBounds(115,30,30, 50);name.setBounds(70, 100,60, 30);for (int i=0;i<maxsize;i++) //记录型数组,记录该桌子上放的是哪些盘子,数组元素值为盘子下标。
汉诺塔java代码
汉诺塔java代码汉诺塔(Hanoi Tower)是经典的递归问题,它涉及到将一组圆盘从一个垂直柱子移动到另一个垂直柱子,中间通过第三个柱子。
这个问题可以通过递归的方式非常优雅地解决。
下面是使用Java编写的汉诺塔问题的代码,代码注释详细解释了每个步骤的含义。
```java/*** 汉诺塔问题的Java实现*/public class HanoiTower {/*** 汉诺塔问题的解决方法** @param n 圆盘的数量* @param from 起始柱子* @param to 目标柱子* @param aux 辅助柱子*/public static void solveHanoi(int n, char from, char to, char aux) {// 如果只有一个圆盘,直接移动到目标柱子if (n == 1) {System.out.println("移动圆盘 1 从柱子 " + from + " 到柱子 " + to);return;}// 将 n-1 个圆盘从起始柱子移动到辅助柱子,目标柱子作为辅助solveHanoi(n - 1, from, aux, to);// 移动第 n 个圆盘到目标柱子System.out.println("移动圆盘 " + n + " 从柱子 " + from + " 到柱子 " + to);// 将 n-1 个圆盘从辅助柱子移动到目标柱子,起始柱子作为辅助solveHanoi(n - 1, aux, to, from);}public static void main(String[] args) {// 圆盘的数量int numberOfDiscs = 3;// 调用解决方法solveHanoi(numberOfDiscs, 'A', 'C', 'B');}}```在这段Java代码中,我们使用了一个递归函数`solveHanoi`来解决汉诺塔问题。
汉诺塔 算法
汉诺塔算法汉诺塔算法是指将汉诺塔问题的解法转换为计算机程序的过程。
汉诺塔问题是一个经典的数学问题,它有三个柱子和一些圆盘,圆盘大小不等,可以套在柱子上。
最初,所有圆盘按从大到小的顺序套在第一个柱子上。
目标是将所有圆盘移动到第三个柱子上,但是移动过程必须遵守以下规则:1. 每次只能将一个圆盘从柱子顶端移动到另一个柱子的顶端。
2. 大圆盘不能放在小圆盘上面。
汉诺塔问题的解法是递归的,即将大问题分解为小问题,直到解决最小的问题。
对于汉诺塔问题,最小的问题是将一个圆盘从一个柱子移动到另一个柱子,这是一个非常简单的问题。
对于一个有n个圆盘的汉诺塔问题,我们可以将其分解为以下三个子问题:1. 将前n-1个圆盘移动到第二个柱子上。
2. 将第n个圆盘从第一个柱子移动到第三个柱子上。
3. 将前n-1个圆盘从第二个柱子移动到第三个柱子上。
以上三个子问题都是汉诺塔问题,可以用同样的方式递归求解。
因此,我们可以使用递归算法解决汉诺塔问题。
在实现递归算法时,我们需要考虑以下几个方面:1. 基本情况:当只有一个圆盘时,直接将它从起始柱子移动到目标柱子即可。
2. 递归调用:对于有n个圆盘的汉诺塔问题,将前n-1个圆盘移动到中间柱子,将第n个圆盘移动到目标柱子,最后将前n-1个圆盘移动到目标柱子。
3. 优化:由于递归算法可能会反复计算某些子问题,我们可以使用记忆化技术或者迭代算法来优化递归算法的效率。
汉诺塔算法是一个经典的递归算法,它不仅有很高的理论价值,而且在实际中也有广泛的应用。
例如,在操作系统中,进程的调度和资源管理也可以使用递归算法来实现。
因此,掌握汉诺塔算法对于程序员来说是非常重要的。
四根柱子汉诺塔问题
Hanoi:为汉诺塔问题一、运行结果二、源程序import java.util.Scanner;/*** 问题描述:* 由原来的三根柱子,变为四根柱子,最终要把a柱子上的全部移到b柱子上** 思路分析:* 假设有n个圆盘,三根柱子,a,b,c,需要把n个盘子(从下往上按照大小顺序摞着)从a柱移动到b 柱,* 再找来了一根一模一样的柱子d,通过这个柱子来更快的把所有的盘子移到第三个柱子上。
* 这道题和之前都有很大的不同,加了一根柱子,意味着有的时候可用3根柱子,有的时候可用4根柱子, * 当把j个小盘子移动到d盘上时,有四根柱子可用,而当把n-j个盘子从a移动到b时,仅有三根柱子可用。
* 这里我们就要找到j的值,使所有移动的次数和最小。
** 解决方法:* 依然采用分治法。
* 首先把j个盘子移动到d柱子上(通过四个柱子可用的算法),需要B[j]次移动,* 然后把n-j个盘子移动到b柱子上(通过三个柱子可用的算法),需要A[n-j]次移动,* 然后把d中的j个盘子移动到b柱子上,需要B[j]次移动。
* 我们可以用j的大小循环,找到移动次数最小的j。
* 首先我们先计算移动的次数:* 核心公式为:count4(4柱子时总移动次数)=2*B[j]+A[i-j],即* j个盘子移动到第四个柱子,然后把剩下的i-j个在第四个不能用的情况下移到第三个** 补充:* 三根柱子时的次数计算* 假设移动n个盘子需要移动f(n)次,所以把n-1个盘子移动到b柱子上,需要移动f(n-1)次,* 然后把第n个盘子移动到c柱子上,需要移动1次,最后把n-1个盘子移动到c柱子上,需要移动f(n-1)次,* 综上所述,一共移动了f(n)=2f(n-1)+1次*/public class Hanoi {static int count = 0; //统计移动次数(可不需要,因为最少次数已经与n的值对应的记录在数组B中,即B[n])/*** 主函数*/public static void main(String[] args) {int n; //盘子数int flag_j; //记录找到的j的值int[] A = new int[65]; // 数组A:用来记录未加第四个柱子时候的移动次数情况int[] B = new int[65]; // 数组B:用来记录加了第四个柱子的情况/*根据三个柱子移动策略给数组A赋值(下面描述是按照将a柱上盘子移动到c柱上的问题来叙述的),即* 假设移动n个盘子需要移动f(n)次,所以把n-1个盘子移动到c柱子上,需要移动f(n-1)次,* 然后把第n个盘子移动到c柱子上,需要移动1次,* 最后把n-1个盘子移动到c柱子上,需要移动f(n-1)次,综上所述,一共移动了f(n)=2f(n-1)+1 次*/A[1] = 1; // 即三个柱子时,当i=1的时候,表示移动一个盘子,只需要移动一次for (int i = 2; i < 65; i++) {// 从i=2开始A[i] = 2 * A[i - 1] + 1; // f(n)=2f(n-1)+1}/** 将n个盘子分为两部分,即前j个和后n-j个* 且把前 j个用四个柱子的方法,后i-j个用三个柱子的方法* 下面主要是找到使移动次数最少的j值*/int count4; //记录四根柱子时,移动的总次数int min; //移动的最少次数,以用来和四个柱子时的其他情况进行比较int[] C = new int[65]; // 数组C:用来记录当前i下找到的的j值C[1] = 0; // 设置i=1时,初始值为0,即只有一个盘子时,令j=0C[2] = 0; // 设置i=2时,初始值为0,即只有两个盘子时,令j=0//注意:此时的i相当于盘子数nfor (int i = 3; i <= 64; i++) {min = A[i]; // 假设没加第四个柱子的结果次数为min的初值B[1] = 1; //可知 i=1 时,即一个盘子从柱子a->d,移动次数为1次B[2] = 3; //i=2时,即两个盘子从柱子a->d,移动次数为3次flag_j = 0;for (int j = 1; j < i; j++) {count4 = 2 * B[j] + A[i - j]; // j个移动到第四个柱子,然后把剩下的i-j个在第四个柱子不能用的情况下,移到第三个柱子/** 如果三根柱子时的次数min 大于四根柱子时的次数flag,则用flag更新min* 并记录下此时j的值,即得到了怎么分割盘子,才能使最终的移动次数最少*/if (min > count4) {min = count4;flag_j = j;}B[i] = min; // 将min赋给B[i],即四根柱子时,i个盘子从a->d 的次数C[i] = flag_j; // 找到了当前i下的j值}}Scanner scanner = new Scanner(System.in);while (true) {System.out.print("请输入一个n值(应为1-64之间的整数,输入0结束程序):");n = scanner.nextInt();if(n == 0) {System.out.println("ByeBye");break;}if(n > 64 || n < 1) {System.out.println("输入的n有误,请重新输入");continue;}char a = 'a', b = 'b', c = 'c', d = 'd';hanoi(n, a, b, c, d, C); // 把n个盘子从a柱子移动到b柱子System.out.println("共移动了: " + B[n] + " 次");System.out.println("共移动了: " + count + " 次");//与B[n]的值是一样的count = 0;//次数置零}}/*** 移动(使用四个柱子的移动方式)*/public static void hanoi(int n, char a, char b, char c, char d, int C[]){ int j = C[n]; //j个盘子使用四个柱子的移动方式if (n > 0) {hanoi(j, a, d, b, c, C);// 把j个盘子移动到d柱子上hanoi_basic_3(n - j, a, b, c);// 把n-j个盘子移动到b柱子上(使用三个柱子的移动方式)hanoi(j, d, b, a, c, C); // 把j个盘子移动到b柱子上}}/*** 把n-j个盘子移动到b柱子上(使用三个柱子的移动方式)*/public static void hanoi_basic_3(int n, char a, char c, char b){ if(n > 0) {hanoi_basic_3(n - 1, a, b, c);// 把n-1个盘子移动到c柱子上move(n, a, c); // 把a移动到chanoi_basic_3(n - 1, b, c, a); // 把第n个盘子移动到c柱子上 }}/*** 在控制台打印移动情况*/public static void move(int n, char a, char c){System.out.println(a + "->" + c);count++;//记录次数}}。
汉诺塔问题——精选推荐
汉诺塔问题汉诺塔问题是⼀个经典的问题。
汉诺塔(Hanoi Tower),⼜称河内塔,源于印度⼀个古⽼传说。
⼤梵天创造世界的时候做了三根⾦刚⽯柱⼦,在⼀根柱⼦上从下往上按照⼤⼩顺序摞着64⽚黄⾦圆盘。
⼤梵天命令婆罗门把圆盘从下⾯开始按⼤⼩顺序重新摆放在另⼀根柱⼦上。
并且规定,任何时候,在⼩圆盘上都不能放⼤圆盘,且在三根柱⼦之间⼀次只能移动⼀个圆盘。
问应该如何操作?分析如果是初次接触类似的问题,乍看之下肯定会感觉⽆从下⼿。
要把64个圆盘从a柱⼦移动到c柱⼦上,第⼀步应该怎么做?虽然可以肯定,第⼀步唯⼀的选择是移动a最上⾯的那个圆盘,但是应该将其移到b还是c呢?很难确定。
因为接下来的第⼆步、第三步……直到最后⼀步,看起来都是很难确定的。
能⽴即确定的是最后⼀步:最后⼀步的盘⼦肯定也是a最上⾯那个圆盘,并且是由a或b移动到c——此前已经将63个圆盘移动到了c上。
也许你会说,管他呢,先随便试着移动⼀下好了。
如果你这么做,你会发现,接下来你会⾯临越来越多类似的选择,对每⼀个选择都“试”⼀下的话,你会偏离正确的道路越来越远,直到你发现你接下来⽆法进⾏为⽌。
如果将这个问题的盘⼦数量减为10个或更少,就不会有太⼤的问题了。
但盘⼦数量为64的话,你⼀共需要移动约1800亿亿步(18,446,744,073,709,551,615),才能最终完成整个过程。
这是⼀个天⽂数字,没有⼈能够在有⽣之年通过⼿动的⽅式来完成它。
即使借助于计算机,假设计算机每秒能够移动100万步,那么约需要18万亿秒,即58万年。
将计算机的速度再提⾼1000倍,即每秒10亿步,也需要584年才能够完成。
注:在我的笔记本电脑上,每秒⼤约能够移动6~8百万步。
虽然64个盘⼦超出了⼈⼒和现代计算机的能⼒,但⾄少对于计算机来说,这不是⼀个⽆法完成的任务,因为与我们⼈类不同,计算机的能⼒在不断提⾼。
分解问题⼀股脑地考虑每⼀步如何移动很困难,我们可以换个思路。
微课-汉诺塔问题教案
本微课适用范围如下所示:课程所属学科:计算机适用专业:计算机应用技术、计算机软件工程、电子信息适用课程:C语言程序设计、C++程序设计、JAVA程序设计、数据结构适用对象:有一定编程基础的同学《汉诺塔问题》微课教案学院(部):软件学院系(教研室):网络教研授课教师:杨珺职称:副教授时间复杂度为:O(2n)程序实现部分汉诺塔问题的递归实现:#include<stdio.h>void hanoi(int n,char A,char B,char C){if(n==1){printf("Move disk %d from %c to %c\n",n,A,C);}else{hanoi(n-1,A,C,B);printf("Move disk %d from %c to %c\n",n,A,C);hanoi(n-1,B,A,C);}}main(){int n;printf("请输入数字n以解决n阶汉诺塔问题:\n");scanf("%d",&n);hanoi(n,'A','B','C');}●汉诺塔算法的非递归实现C++源代码#include <iostream>using namespace std;//圆盘的个数最多为64const int MAX = 64;//用来表示每根柱子的信息struct st{int s[MAX]; //柱子上的圆盘存储情况int top; //栈顶,用来最上面的圆盘char name; //柱子的名字,可以是A,B,C中的一个int Top()//取栈顶元素{return s[top];}int Pop()//出栈return s[top--];}void Push(int x)//入栈{s[++top] = x;}} ;long Pow(int x, int y); //计算x^yvoid Creat(st ta[], int n); //给结构数组设置初值void Hannuota(st ta[], long max); //移动汉诺塔的主要函数int main(void){int n;cin >> n; //输入圆盘的个数st ta[3]; //三根柱子的信息用结构数组存储Creat(ta, n); //给结构数组设置初值long max = Pow(2, n) - 1;//动的次数应等于2^n - 1 Hannuota(ta, max);//移动汉诺塔的主要函数system("pause");return 0;}void Creat(st ta[], int n){ta[0].name = 'A';ta[0].top = n-1;//把所有的圆盘按从大到小的顺序放在柱子A上for (int i=0; i<n; i++)ta[0].s[i] = n - i;//柱子B,C上开始没有没有圆盘ta[1].top = ta[2].top = 0;for (int i=0; i<n; i++)ta[1].s[i] = ta[2].s[i] = 0;//若n为偶数,按顺时针方向依次摆放 A B Cif (n%2 == 0){ta[1].name = 'B';ta[2].name = 'C';}else //若n为奇数,按顺时针方向依次摆放 A C Bta[1].name = 'C';ta[2].name = 'B';}}long Pow(int x, int y){long sum = 1;for (int i=0; i<y; i++)sum *= x;return sum;}void Hannuota(st ta[], long max){int k = 0; //累计移动的次数int i = 0;int ch;while (k < max){//按顺时针方向把圆盘1从现在的柱子移动到下一根柱子ch = ta[i%3].Pop();ta[(i+1)%3].Push(ch);cout << ++k << ": " <<"Move disk " << ch << " from " << ta[i%3].name <<" to " << ta[(i+1)%3].name << endl;i++;//把另外两根柱子上可以移动的圆盘移动到新的柱子上if (k < max){ //把非空柱子上的圆盘移动到空柱子上,当两根柱子都为空时,移动较小的圆盘if (ta[(i+1)%3].Top() == 0 ||ta[(i-1)%3].Top() > 0 &&ta[(i+1)%3].Top() > ta[(i-1)%3].Top()){ch = ta[(i-1)%3].Pop();ta[(i+1)%3].Push(ch);cout << ++k << ": " << "Move disk "<< ch << " from " << ta[(i-1)%3].name<< " to " << ta[(i+1)%3].name << endl;}else{ch = ta[(i+1)%3].Pop();ta[(i-1)%3].Push(ch);cout << ++k << ": " << "Move disk "<< ch << " from " << ta[(i+1)%3].name<< " to " << ta[(i-1)%3].name << endl;}}}}汉诺塔问题的非递归实现#include <stdio.h>#include <math.h>#include <stdlib.h>//第0位置是柱子上的塔盘数目int zhua[100]={0},zhub[100]={0},zhuc[100]={0};char charis(char x,int n)//左右字符出现顺序固定,且根据n值奇偶而不同{switch(x){case 'A':return (n%2==0)?'C':'B';case 'B':return (n%2==0)?'A':'C';case 'C':return (n%2==0)?'B':'A';default:return '0';}}void print(char lch,char rch)//打印字符{if(lch=='A'){switch(rch){case 'B':zhub[0]++;zhub[zhub[0]]=zhua[zhua[0]]; zhua[zhua[0]]=0;zhua[0]--;break;case 'C':zhuc[0]++;zhuc[zhuc[0]]=zhua[zhua[0]]; zhua[zhua[0]]=0;zhua[0]--;break;default:break;}}if(lch=='B'){switch(rch){case 'A':zhua[0]++;zhua[zhua[0]]=zhub[zhub[0]]; zhub[zhub[0]]=0;zhub[0]--;break;case 'C':zhuc[0]++;zhuc[zhuc[0]]=zhub[zhub[0]]; zhub[zhub[0]]=0;zhub[0]--;break;default:break;}}if(lch=='C'){switch(rch){case 'A':zhua[0]++;zhua[zhua[0]]=zhuc[zhuc[0]];zhuc[zhuc[0]]=0;zhuc[0]--;break;case 'B':zhub[0]++;zhub[zhub[0]]=zhuc[zhuc[0]];zhuc[zhuc[0]]=0;zhuc[0]--;break;default:break;}}printf("\t");int i;printf("(");for(i=1;i<=zhua[0];i++)printf(" %d ",zhua[i]);printf(")");printf("(");for(i=1;i<=zhub[0];i++)printf(" %d ",zhub[i]);printf(")");printf("(");for(i=1;i<=zhuc[0];i++)printf(" %d ",zhuc[i]);printf(")");printf("\n");}void Hannuo(int n){//分配2^n个空间bool *isrev;isrev=(bool *)malloc(sizeof(bool)*(int)pow(2,n)); for(int i=1;i<pow(2,n);i++)//循环计算是否逆序for(int ci=2;ci<=n;ci++){for(int zixh=(int)pow(2,ci-1);zixh<pow(2,ci);zixh+=4) //初始值重复一次,自增值可加4,减少循环次数。
汉诺塔问题动态演示
n a b c
void hanoi ( int n, char a, char b, char c ) { if ( n >= 1 ) { hanoi ( n-1, a, c, b) ; printf(“%c -->%c\n“,a,c); hanoi (n-1, b, a, c) ; } }
H(n,A,B,C)
n a b c
void hanoi ( int n, char a, char b, char c ) { if ( n >= 1 ) { hanoi ( n-1, a, c, b) ; printf(“%c -->%c\n“,a,c); hanoi (n-1, b, a, c) ; } }
H(n,A,B,C)
H ( 3, A, B, C )
Stack
Output 0 A C B 1 A B C 2 A C B 3 A B C
H(n-1,a,c,b) H ( 2, A, C, B )
H(n-1,a,c,b) H ( 1, A, B, C )
H(n-1,a,c,b) H ( 0, A, C, B )
n a b c
// 汉诺塔
void main () { int n ;
printf( " Input the number of diskes:\n “) ; scanf(“%d”,&n) ;
hanoi ( n, 'A' , 'B' , 'C' ) ; }
Stack
Output
n a b c
// 汉诺塔
void main () { int n ;
汉诺塔问题动态演示汉诺塔问题求解汉诺塔问题汉诺塔问题非递归汉诺塔游戏汉诺塔豪华版汉诺塔汉诺塔递归算法汉诺塔时间复杂度汉诺塔java汉诺塔小游戏
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
// 用于-塔的空层显示
StringBuilder spaces = new StringBuilder();
{
/**
*diskNum是盘子的数量
*/
private int diskNum ;
/**
*各个组件的句柄
*/
private JButton begin, stop;
private JLabel lDiskNum;
private JTextField text;
printPagodas(); // 打印图形
}
}
import javax.swing.*;
import java.awt.geom.*;
import java.awt.event.*;
import java.awt.*;
public class Hanio extends JApplet implements ActionListener, Runnable
fromNum = i+1;
}
if (mapping[i] == to) {
toNum = i+1;
}
}
System.out.println("从 " + fromNum + " 号塔往 " + toNum + " 号塔\r\n");
// 每一层由 2*tiers-1 个格子组成,代表盘子大小的"^"格子由空格隔开
for(int k = 0; k < tiers - i; k++) builder.append(" "); // 盘子左边的空格,数量为 [2*tiers-1-(2*i-1)]/2 = tiers-i, 右边相同
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");
preparePagoda(pagoda1, tiers);
System.out.println("初始状态:");
printPagodas();
hanoi(tiers, pagoda1, pagoda2, pagoda3);
java汉诺塔.txt始终相信,这世间,相爱的原因有很多,但分开的理由只有一个--爱的还不够。人生有四个存折:健康 情感 事业和金钱。如果健康消失了,其他的存折都会过期。 //汉诺塔
public class NewHanoi {
public static int tiers = 4; // tiers 层数
} catch (Exception e) { System.out.print(spaces);
}
try { System.out.print("-" + pagoda3.get(i) + "-\t");
} catch (Exception e) { System.out.print(spaces);
public void init()
{
Container content = getContentPane();
content.setLayout(new BorderLayout());
lDiskNum = new JLabel("盘子的数目");
text = new JTextField(8);
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) {
System.out.println("最后结果:");
printPagodas();
}
// --准备盘子(添加-字符串) (源塔)上
private static void preparePagoda(List<String> srcPagoda, int tiers) {
spaces.append("-"); // --添加塔的左外框
for(int i = 0; i < 2*tiers-1; i++) spaces.append(" "); // 空层显示用空格
spaces.append("-\t"); // --添加塔的右外框和塔间间隔
{
/**
*消除以前画的盘子
*/
for(int j=adisk.length, i=0; --j>=0; i++ )
pane.setLayout(new FlowLayout());
pane.add(lDiskNum);
pane.add(text);
pane.add(begin);
pane.add(stop);
content.add(pane, BorderLayout.SOUTH);
// 用于拼装塔层的容器
StringBuilder builder = new StringBuilder();
// 源塔的每一层加盘子,从底层开始, i ‘代表’盘子的直径大小,等于组成盘子的"^"个数
for(int i = tiers; i > 0; i--){
if(moveNum == 1){ // 递归到移动一个盘子时,使用 move 方法
moveTheTopOne(from, to);
return;
}
// 将实现分为三步,一,将源塔底盘上方的所有盘子移至中间塔(递归);二,将底盘移到目标塔;三,将中间塔上的所有盘子移到目标塔上(递归)。
String theTopOne = from.remove(from.size() - 1);
to.add(theTopOne);
// 打印图形,每移动一下,打印图形显示
System.out.println("********** print ***********\r\n");
}
System.out.print("\r\n");
}
}
// 这个方法(递归的核心方法)从指定的源塔上移动-指定数量的盘子-到指定的目标塔上
public static void hanoi(int moveNum, List<String> from, List<String> middle, List<String> to) {
private static List<String> pagoda1 = new ArrayList<String>(); // 静态指针
private static List<String> pagoda2 = new ArrayList<String>();
private static List<String> pagoda3 = new ArrayList<String>();
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()); // 添加到塔上
begin = new JButton("开始");
begin.addActionListener(this);
stop = new JButton("停止");
stop.addActionListener(this);
pane = new JPanel();
// 确定塔的序号
int fromNum = 0, toNum = 0;
for (int i = 0; i < mapping.length; i+] == from) {