汉诺塔课程设计.docx
《汉诺塔课程设计.docx》由会员分享,可在线阅读,更多相关《汉诺塔课程设计.docx(27页珍藏版)》请在冰豆网上搜索。
汉诺塔课程设计
课程设计(论文)任务书
软件学院学 院 软件工程专 业4 班
一、课程设计(论文)题目 Hannoi塔
二、课程设计(论文)工作自2011年12月12日起至2011年12月16日止。
三、课程设计(论文)地点:
软件学院实训中心
四、课程设计(论文)内容要求:
1.本课程设计的目的
(1)掌握Java语言的程序设计方法;
(2)理论联系实际,进一步提高学生的软件开发技术;
(3)培养学生分析、解决问题的能力;
(4)提高学生实践论文撰写能力。
2.课程设计的任务及要求
1)课程设计任务:
设计GUI界面的Hannoi塔,用户可以通过拖动鼠标移动各个塔上的盘子,程序也
可以自动演示盘子的移动过程。
2)创新要求:
1.有三个表示塔的对象,分别命名为A、B和C。
A塔上有若干个盘子,盘子的大
小不等,并按着大小顺序依次摆放在A塔上,大盘在下,小盘在上。
用户可以用鼠
标拖动盘子,把A塔上的盘子全部移动到另外两个塔中的任何一个塔上。
要求每
每次只能移动一个盘子,在任何时候不允许大盘压在小盘的上面。
2.用户也可以选择让程序自动演示。
选择自动演示后,程序将以动画形式演示把A
塔上的盘子全部移到C塔的过程,并将移动过程以文本形式显示在一个文本区中。
3)课程设计论文编写要求
(1)课程设计任务及要求
(2)设计思路--工作原理、功能规划
(3)详细设计---数据分析、算法思路、类设计、功能实现(含程序流程图、主要代
码及注释)、界面等。
(4)运行调试与分析讨论---给出运行屏幕截图,分析运行结果,有何改进想法等。
(5)设计体会与小结---设计遇到的问题及解决办法,通过设计学到了哪些新知识,
巩固了哪些知识,有哪些提高。
(6)参考文献(必须按标准格式列出,可参考教材后面的参考文献格式)
(7)报告按规定排版打印,要求装订平整,否则要求返工;
(8)课设报告的装订顺序如下:
封面---任务书---中文摘要---目录----正文---附录
(代码及相关图片)
(9)严禁抄袭,如有发现,按不及格处理。
4)课程设计评分标准:
(1)学习态度:
20分;
(2)程序检查:
20分;
(3)课设答辩:
20分;
(4)课设报告:
40分。
5)参考文献:
(1)丁振凡.Java语言实用教程(第2版)[M].清华大学出版社.2008.1
6)课程设计进度安排
1.准备阶段(4学时):
选择设计题目、了解设计目的要求、查阅相关资料
2.程序模块设计分析阶段(4学时):
程序总体设计、详细设计
3.代码编写调试阶段(8学时):
程序模块代码编写、调试、测试
4.撰写论文阶段(4学时):
总结课程设计任务和设计内容,撰写课程设计论文
学生签名:
2011年12月12日
课程设计(论文)评审意见
(1)学习态度(20分):
优( )、良( )、中( )、一般( )、差( );
(2)程序检查(20分):
优( )、良( )、中( )、一般( )、差( );
(3)课设答辩(20分):
优( )、良( )、中( )、一般( )、差( );
(5)论文撰写(40分):
优( )、良( )、中( )、一般( )、差( );
评阅人:
钟小妹职称:
讲师
2011年12月16日
中文摘要
汉诺塔:
汉诺塔(又称河内塔)问题是源于印度一个古老传说的益智玩具。
大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上安大小顺序摞着64片黄金圆盘。
大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。
并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。
汉诺塔的游戏规则:
把三根柱子分别命名为A,B,C。
大小不同的圆盘起始按照由下至上由大到小的顺序放在A柱上,最后需要通过移动使之按照由下至上由大到小的顺序放在C柱上,且在移动过程中不允许有大小错误,只允许小盘放在大盘上面。
移到C柱即成功。
本汉诺塔游戏程序是使此古老的游戏通过JAVA算法的实现在计算机上运行,且不丢失任何规则。
目 录
一、课程设计任务及要求
设计内容
设计GUI界面的Hannoi塔,用户可以通过拖动鼠标移动各个塔上的盘子,程序也可以自动演示盘子的移动过程。
设计要求
1.有三个表示塔的对象,分别命名为A、B和C。
A塔上有若干个盘子,盘子的大小不等,并按着大小顺序依次摆放在A塔上,大盘在下,小盘在上。
用户可以用鼠标拖动盘子,把A塔上的盘子全部移动到另外两个塔中的任何一个塔上。
要求每次只能移动一个盘子,在任何时候不允许大盘压在小盘的上面。
2.用户也可以选择让程序自动演示。
选择自动演示后,程序将以动画形式演示把A塔上的盘子全部移到C塔的过程,并将移动过程以文本形式显示在一个文本区中。
二、需求分析
2.1界面及布局设计
系统的整体布局为BorderLayout布局,采用了按钮、面板、复选框、文本框、文本区和拆分窗格等组件,按钮的有以下几个功能:
1.可以改变盘子数目;2.可以改变盘子大小;3.可以改变盘子的颜色和背景颜色;4.可以重新开始游戏和自动演示搬运盘子;5.可以保存自动演示的文本信息;复选框可以控制背景音乐的播放和暂停,拆分窗格放入几个面板,面板全都是采用空布局。
2.2A、B、C座的实现方法
Java支持图形与图像功能,A,B,C座的实现就是利用java的这个功能,就是利用java2D技术。
java拥有强大的二维图形处理能力,绘制A,B,C座就是使用paint(Graphicsg)方法,通过Graphics对象g调用drawLine()方法来绘制三条竖线,然后通过Graphics对象g调用fillRect()方法绘制出矩形区域,然后根据盘子数目在每条竖线上调用g.fillOval()方法绘制相同数目点,最后调用drawString()方法绘出A座,B座,C座,这样就实现了A座,B座,C座的绘制。
2.3圆盘的实现方法
JButton是java系统提供的类,实现圆盘的类Disc继承JButton类,所以Disc类是JButton的一个子类,创建的一个对象是Tower容器中的一个按钮用来表示Tower中的“盘子”,盘子对象是一个按钮,这样可以加入监视器,从而可以移动盘子。
2.4改变背景和盘子颜色的方法
Javax.Swing包中有类JColorChooser,该类有一个静态方法publicstaticColorshowDialog(Componentcomponent,Stringtitle,ColorinitalColor),该方法是创建一个颜色对话框,颜色对话框可果然那句用户在颜色对话框中选择的颜色返回一个颜色对象,当获取到这个颜色对象后,组件通过调用setBackground()方法来设置背景颜色和盘子颜色。
三、设计思路
本程序要求实现用图形界面,画出3个柱子和若干个大小不一的圆盘,同时圆盘数目可以人工设定,当点击“开始”按钮后,系统自动展现圆盘的移动过程,从而实现汉诺塔问题,其中圆盘移动速度是每秒移动一次。
汉诺塔算法属于递归算法,该算法过程为:
假定要把n个盘子按题目规定由a杆借助b杆移动到c杆。
模拟这一过程的算法称为autoMoveDisk(n,a,b,c)。
则有:
第一步:
先把上面的n-1个盘子设法借助b杆放到c杆,如图1.1中的箭头1)所示,记做autoMoveDisk(n,a,c,b);
第二步:
把第n个盘子从a杆直接移到b杆,如图1.1中箭头2)所示;
第三步:
把c杆上的n-1个盘子借助a杆移到b杆,如图1.1中的箭头3)所示,记做autoMoveDisk(n,c,a,b);
1、本程序定义了四个类,分别为:
1)Disk类,此类是继承了Button类,是他的一个子类,用于实现画出图形界面中的盘子,包括定义盘子数量,设置盘子的颜色,判断柱子最上面是否有盘子(设置和返回盘子的状态)。
该类在TowerPoint类和HannioTower类中都有被调用。
2)TowerPoint类,本类用于实现定义盘子的放置位置,即一个坐标点(盘子的中心点在塔上的位置),同时还能够判断柱子上某点上是否有盘子(设置和返回该点上盘子的状态),还能够完成在该点上放置盘子,将盘子加到容器里。
该类的初始化和真正实现是在HannioTower类中。
3)HannioTower类,此类中主要包括两个部分:
第一个部分:
设置塔上点的属性,根据盘子数来存储三根柱子上点的坐标(即盘子的放置位置)并设置该点上没有盘子。
同时设置盘子的属性,包括设置盘子的宽度和高度以及将盘子放到柱子上,并设置柱子最上面有盘子。
在图形界面上画柱子(即三根直线和一根水平直线),灰色矩形长条作为底座,用红色点标注盘子的放置位置和用A、B和C来标明三根柱子。
第二个部分:
也是核心部分,即汉诺塔算法通过函数的实现。
该算法在上面已有介绍,但在算法的第二步中(把第n个盘子从a杆直接移到b杆),要考虑到取a杆上的第n个盘子时,要判断是否有该盘子和获得该盘子,并获得该盘子的位置(为设置拿走后该位置上没有盘子的属性),以及在塔中获得盘子的放置位置。
最后将盘子的整个移动过程追加于文本域中。
4)Tower类,该类为主类。
主类使用Frame容器作为JavaApplication程序图形用户界面的。
用于实现整个图形界面的布局(界面布局为边界布局),两个按钮、下拉按钮和文本域的定义及事件的监听。
若点击“自动演示”按钮,判断线程是否存活,若不存活则创建线程;若点击“重新开始”按钮,若线程不存活,则重新构建图形界面,恢复到原始状态;若重新选择盘子数,则也重新构建图形界面,恢复到新的原始状态。
线程的实现是通过该类实现了Runnable接口,并在该类中定义Runnable接口的run()方法,该方法代表了线程的执行起点。
四、详细设计
程序流程图(汉诺塔程序流程图)
程序代码说明
程序中引入的包:
packagecode;
importjavax.swing.*;
importjava.awt.*;
importjava.awt.event.*;
(1)盘子类:
类名:
Disk
作用:
定义图形界面中的盘子属性
继承的父类名:
Button
publicclassDiskextendsButton{}
定义的对象:
intnumber//盘子的个数
booleanisTop=false//判断柱子最上面是否有盘子
主要成员方法:
publicbooleangetIsTop()//返回最上面是否有盘子的属性
publicvoidsetIsTop(booleanb)//设置最上面是否有盘子的属性
publicintgetNumber()//返回盘子个数
(2)盘子的放置位置类
类名:
TowerPoint
作用:
定义塔上点的坐标,即盘子的放置位置
publicclassTowerPoint{}
定义的对象:
intx,y//塔上的点位置,即盘子的放置位置
booleanisHaveDisk//判断点上是否有盘子
Diskdisk//定义盘子类的对象
HannoiTowercon//定义一个HannoiTower类的对象
主要成员方法:
publicbooleangetIsHaveDisk()//返回点上是否有盘子的属性
publicvoidsetIsHaveDisk(booleanboo)//设置点上是否有盘子的属性
publicintgetX()//获得点位置坐标x
publicintgetY()//获得点位置坐标y
publicvoidputDisk(Diskdisk,HannoiTowercon)//在点上放盘子
publicDiskgetDisk()//返回Disk类型
(3)汉诺塔模拟程序类
类名:
HannoiTower
作用:
设置踏上点属性、设置盘子属性、汉诺塔模拟程序
继承的父类名:
JPanel
publicclassHannoiTowerextendsJPanel{}
定义的对象:
TowerPointpoint[]//塔上点数组
booleanmove=false//判断是否移动
Diskdisks[]//盘子数组
intdiskNum=0//定义盘子个数
intwidth,height//盘子的宽度和高度
chartowerName[]={'A','B','C'}//塔名
TextAreainfoArea//定义一个文本域
intautoNum=1//计算步数
主要成员方法:
publicvoidpaint(Graphicsg)//画主界面中的柱子
publicvoidautoMoveDisk(intdiskNum,charone,chartwo,charthree)//自动演示函数
publicDiskgetTopDisk(chartowerN)//取最上面的盘子
publicintgetTopDiskUp(chartowerN)//在塔中获取盘子的放置位置
publicintgetTopDiskPosition(chartowerN)//获得最上面盘子的位置
publicvoidpause()//盘子移动速度是每秒移动一次
(4)主类
类名:
Tower
作用:
设置界面布局,和进行事件监听
继承的接口名:
ActionListener,ItemListener,Runnable
继承的父类名:
Frame
publicclassTowerextendsFrameimplementsActionListener,ItemListener,Runnable{}
定义的对象:
HannoiTowertower//定义一个HannoiTower类的对象
JButtonrenew,auto//定义两个按钮
ChoicediskNumComBox//定义一个下拉按钮
chartowerName[]={'A','B','C'}//定义塔名
intdiskNum,diskWidth,diskHeight//存储盘子数目、宽度和高度
Threadthread//定义一个线程
TextAreainfoArea//定义一个文本域
主要的成员方法:
publicvoidactionPerformed(ActionEvente)//事件的响应程序
publicvoiditemStateChanged(ItemEvente)//事件的响应程序
publicvoidrun()//线程的启动
publicstaticvoidmain(Stringargs[])//主函数
五、运行调试与分析讨论
(1)调试过程中遇到的主要问题及解决方法
如何利用线程控制盘子的移动?
Java语言是第一个语言本身就支持线程的主流编程语言,其对线程的支持主要通过java.lang.Thread类和java.lang.Runnable接口来实现。
本类实现了Runnable接口,并在该类中定义Runnable接口的run()方法。
当点击“自动演示”时,创建线程,从新布局界面。
在此函数中用到了remove()函数,它是Frame中的函数,从此窗体中移除指定的菜单栏。
如何获得盘子的宽度和长度?
以及如何将盘子放到指定的位置?
经过上网查询,获得盘子的宽度和长度需要getBounds()此函数,它以Rectangle对象的形式获取组件的边界。
如果不知道如何将盘子放到指定的指定的位置,则得到如图1的结果:
图1
为了使盘子放在指定的位置,需要setBounds()此函数,它能移动组件并调整其大小,他有四个参数,前两个参数表示控件的位置坐标,后面两个参数表示控件的宽度和高度。
在汉诺塔算法的第二步中,如何把第n个盘子从a杆移到b杆?
要考虑到取a杆上的第n个盘子时,要判断是否有该盘子和获得该盘子,并获得该盘子的位置(为设置拿走后该位置上没有盘子的属性),以及在塔中获得盘子的放置位置。
在paint()函数中super.paint(g),它同repaint()的功能是一样的,都是重新画界面。
当执行汉诺塔算法时,如果将盘子从一个塔上移动到另一个塔上时,该盘子应该从第一个塔上移除,否则会出现下面的情况:
图2
盘子移动后,仍然在之前的柱子上,因此需要用到Frame中的remove()函数用来移除。
正确结果如图3:
图3
(2)程序运行的时空效率分析
该应用程序并没使用多少数据结构的知识,主要是在求解汉诺塔问题时,涉及到递归调用的算法。
所谓递归,就是一个直接调用自己或通过一系列的调用语句间接地调用自己的过程。
随着盘子的增多,它占用的时间也会越来越多,n个盘子从一根杆移到另一根杆需要2n-1次。
同时还有点的存储和盘子的存储都用到了数组。
其他的部分只是使用了面向对象中的方法和对象,都是一些基本的语句,并没有用到多少数学算法。
(3)测试数据集
分别编译这4个Java源文件,或运行“javac*.java”命令,编译全部的源文件,然后运行主文件,即Tower类。
初始化界面,结果如图4:
图4
点击下拉按钮,选中3个盘子,结果如图5:
图5
结果分析:
当在下拉按钮中选中3时,事件监听者会调用事件响应程序,即publicvoiditemStateChanged(ItemEvente),重新构建界面,盘子数设置为3,同时将文本域设置为空,重新画盘子数
点击“自动演示”后,结果如图6:
图6
结果分析:
点击“自动演示”按钮后,会根据汉诺塔算法自动将盘子从A塔转移到C塔上,同时将移动过程追加到文本域中。
点击“重新开始”,结果如图7:
图7
结果分析:
点击“重新开始”按钮后,他会判断如果不存活的话,就会从此窗体移除指定的菜单栏,然后从新设置文本域和从画HannoiToewer类中的界面。
点击下拉按钮,选中5个盘子,结果如图8:
图8
六、设计体会与小结
现在,计算机在我们生活中日趋重要,计算机已经影响到我们生活的方方面面,很多时候我们都离不开计算机,如何学好计算机是我们当前应解决的问题,特别是作为软件工程专业的学生来说。
现在我们用计算机完成日常的办公及休闲时间的娱乐,虽然现在有很多的软件在我们生活中存在,但是我们也希望有朝一日在一个新的程序下署下我们的名字,Hannoi塔游戏是一个常见的智力游戏,但在电脑上运用JAVA的程序实现使得很容易地得到最快的解答。
这个Hannoi塔游戏是在原有的程序基础上增加了改变盘子大小功能、改变背景颜色功能、改变盘子颜色功能、按键位置以及自动演示的功能,由于是在原有的基础上修改的,所以做起来比较简单,没有花费太多的时间。
当然在编程过程中也遇到很多小问题,有些问题比较简单但就不知道错在哪里,后来经过自己的不断调试,这个Hannoi塔游戏终于大功告成。
经过编写这个Hannoi塔游戏,我认识到应该注意细节问题,虽然是很小的问题,但可以提高自己编程的能力,而且还可以培养自己编程的严谨性,同时还可以为以后的编程积累经验。
编写完这个Hannoi塔游戏,我发现自己有很多的不足,我想如果让我来单独来编写这个游戏,我感觉很吃力,因为这个游戏涉及到好多算法。
七、参考文献
[1]丁振凡,薛清华.JAVA语言程序设计.北京:
清华大学出版社,2010
[2]miao471236401,
[3]charmer21
附代码:
(1)Disk.java
packagecode;
importjava.awt.*;
publicclassDiskextendsButton{
intnumber;//盘子的个数
publicDisk(intnumber){this.number=number;
setBackground(Color.yellow);}
publicintgetNumber(){returnnumber;}}
(2)TowerPoint.java
packagecode;
importjava.awt.*;
publicclassTowerPoint{
intx,y;//塔上的点位置,即盘子的放置位置
booleanisHaveDisk;//判断点上是否有盘子
Diskdisk;HannoiTowercon;
publicTowerPoint(intx,inty,booleanboo){this.x=x;this.y=y;isHaveDisk=boo;}
publicbooleangetIsHaveDisk(){returnisHaveDisk;}
publicvoidsetIsHaveDisk(booleanboo){isHaveDisk=boo;}
publicintgetX(){returnx;}//获得点位置坐标
publicintgetY(){returny;}
publicvoidputDisk(Diskdisk,HannoiTowercon){//在点上放盘子
this.con=con;con.setLayout(null);//设置布局
this.disk=disk;con.add(disk);//加盘子到容器中
intw=disk.getBounds().width;//获得盘子的长和宽getBounds()以Rectangle对象的形式获取组件的边界
inth=disk.getBounds().height;
disk.setBounds(x-w/2,y-h/2,w,h);//setBounds()移动组件并调整其大小,控件位置坐标,后面是宽度和高度
isHaveDisk=true;con.validate();}
publicDiskgetDisk(){returndisk;}}
(3)HannoiTower.java
packagecode;
importjavax.swing.*;
importjava.awt.*;
publicclassHannoiTowerextendsJPanel{
TowerPointpoint[];//塔上点数组
booleanmove=false;//判断是否移动
Diskdisks[];//盘子数组
intdiskNum=0;//定义盘子个数
intwidth,height;//盘子的宽度和高度
chartowerName[]={'A','B','C'};//塔名
TextAreainfoArea;
intautoNum=1;//计算步数
publicHan