数据结构课程设计汉诺塔问题.docx
《数据结构课程设计汉诺塔问题.docx》由会员分享,可在线阅读,更多相关《数据结构课程设计汉诺塔问题.docx(23页珍藏版)》请在冰豆网上搜索。
![数据结构课程设计汉诺塔问题.docx](https://file1.bdocx.com/fileroot1/2023-2/8/971eb004-f3c8-4c76-a9b7-19222342f071/971eb004-f3c8-4c76-a9b7-19222342f0711.gif)
数据结构课程设计汉诺塔问题
1.系统需求分析
1.1问题描述
(一)、课程设计题目:
汉诺塔问题
(二)、目的与要求:
1、目的:
(1)要求学生达到进一步熟练掌握C语言的基本知识和技能;
(2)基本掌握利用VC++6.0制作页面的基本思路和方法;
(3)能够利用所学的基本知识和技能,解决简单的汉诺塔问题。
2、基本要求:
(1)要求利用VC++6.0以及MFC控件来完成系统的设计;
(2)要求在设计的过程中,建立清晰的类层次;
(3)在系统中定义类,每个类中要有各自的属性和方法;
(4)在系统的设计中,至少要用到C中的一种算法。
3、创新要求:
在基本要求达到后,可进行创新设计,如根据查找结果进行修改的功能。
4、写出设计说明书
(三)、设计方法和基本原理:
1、问题描述(功能要求):
界面划出大小不等,颜色不同的矩形块分别代表各盘子,盘子规模n为1~10,并可以选择人工控制演示和系统自动运行演示,如果是自动则还要输入演示速度。
在界面的上方显示正在移动的盘子的源座和目标座。
用人工操作时,按任意键移动一个盘子,这样可以清楚每一步过程。
如果是自动运行,可以选择移动一步的暂停时间。
要求用TurboC或VC6.0MFC实现的汉诺塔问题的图形程序。
设计思路:
用栈存放塔,定义三个堆栈,用来表示三个塔座,栈的每个结点类型为结构体,其中数据域存放盘子的代号,根据代号计算盘子的大小。
Top为塔的栈顶指针,即每个塔的具体高度。
例如,结构体可以定义如下:
StructH
{intdata[15];/*存放每个盘的代号*/
inttop;/*每个塔的具体高度*/
}num[3];
2、问题的解决方案:
根据系统功能要求,可以将问题解决分为以下步骤:
(1)利用VC++中的MFC控件制作出汉诺塔运行页面;
(2)完成类中各个成员函数的定义;
(3)完成系统的应用模块,根据不同按键的功能,在源程序中填入相应的代码;
(4)功能调试;
(5)完成系统总结报告以及系统使用说明书。
2.概要设计
2.1设计思路
对于一个类似的这样的问题,任何一个人都不可能直接写出移动盘子的每一个具体步骤。
可以利用这样的统筹管理的办法求解:
我们假设把该任务交给一个僧人,为了方便叙述,将他编号为64。
僧人自然会这样想:
假如有另外一个僧人能有办法将63个盘子从一个座移到另一个座,那么问题就解决了,此时僧人64只需这样做:
1.命令僧人63将63个盘子从A座移到C座
2.自己将最底下的最大的一个盘子从A座移到C座
3.再命令僧人63将63个盘子从B座移到C座
为了解决将63个盘子从A座移到B座的问题,僧人63又想:
如果能再有一个僧人62能将62个盘子移动到另一座,我就能将63个盘子从A座移动到B座。
他是这样做的:
1.命令僧人62将62个盘子从A移动到C
2.自己将一个盘子从A座移动到B座
3.再命令僧人62将62个盘子移到B座
再进行一次递归。
如此“层层下放”,直到后来找到第2个僧人,让他完成将2个盘子从一个座移到另一个座,进行到此,问题就解决了。
最后找到第1个僧人,让他完成将一个盘子从一个座移动到另一个座,至此,全部工作已经完成,都是可以执行的。
按照如此的思路设计递归算法,很容易得出盘子的移动方案。
另外是图形演示盘子的移动过程。
为了能够更加形象的表示盘子的移动过程。
在设计图形演示的时候,我们采用了图形动态演示。
首先我们将字幕、柱子、以及提示信息等等屏幕内容设置成固定不变,我们这里称之为舞台。
我们将盘子看作对象,一个盘子一个对象。
在设计演示过程的时候,只需要将盘子对象放置于二维界面中的不同信置,通过刷新屏幕,实现动画显示。
2.2系统总体设计
先对程序进行各功能类的定义,定义汉诺塔,显示塔的定义,运行盘子移动的函数,一般可以使用移动、显示等功能,运用数据结构的相关知识,利用一定的算法制作出汉诺塔程序。
能输入塔盘的数量(10以内)和塔盘移动速度,支持人和电脑操作,并且显示移动过程和移动次数,实现汉诺塔的动态掩饰,总的设计思路如下图所示:
该出租车计费系统由四个模块组成,分别是:
塔盘数量设置:
在1到10之间
移动速度调节:
以1000为一秒,输入移动速度
操作对象选择:
有人和电脑连个对象选择
移动过程显示:
将盘子移动的过程显示出来
各模块之间的关系为:
图1.汉诺塔功能结构体图
2.3程序流程图
2.3.1塔盘数量设置
图2.1塔盘数量设置部分
2.3.2移动速度调节
图2.2移动速度调节部分
2.3.3操作对象选择
图2.3操作对象选择部分
2.3.4汉诺塔求解流程图
图2.4汉诺塔求解流程图
3.详细设计
3.1模块设计
3.1.1塔和塔显示的定义
structT
{
inth;//塔的高度
intx;//塔的第一个盘的x坐标,y坐标等于(7+n-塔的高度h)
intl;//塔的第一个盘的长度
}ta[3]={{10,15,2},{0,0,0},{0,0,0}};
charhnt[18][79]={
{""},
{""},
{""},
{"╔════════════════════════════════════╗"},
{"║║"},
{"║║"},
{"║║"},
{"║▆║"},
{"║▆▆║"},
{"║▆▆▆║"},
{"║▆▆▆▆║"},
{"║▆▆▆▆▆║"},
{"║▆▆▆▆▆▆║"},
{"║▆▆▆▆▆▆▆║"},
{"║▆▆▆▆▆▆▆▆║"},
{"║▆▆▆▆▆▆▆▆▆║"},
{"║▆▆▆▆▆▆▆▆▆▆║"},
{"╚════════════════════════════════════╝"}};
intn;
intsum=0;
intcomputerorpeople=1;
intspeed=0;
voidcount_ta_1(intta_1)
{
inti;
intj;
intk=0;
for(i=7;i<7+n;i++)
for(j=4+ta_1*24;j<28+ta_1*24;j++)
{
if(hnt[i][j]!
='')
{
for(;hnt[i][j+k]!
='';k++);
ta[ta_1].x=j;
ta[ta_1].l=k;
return;
}
}
}
3.1.2塔盘移动的定义
voidmove(intta_1,intta_3)
{
inti;
sum++;
ta[ta_3].h++;
ta[ta_3].x=ta[ta_1].x+(ta_3-ta_1)*24;
ta[ta_3].l=ta[ta_1].l;
for(i=0;i{
hnt[7+n-ta[ta_3].h][ta[ta_3].x+i]=hnt[7+n-ta[ta_1].h][ta[ta_1].x+i];
hnt[7+n-ta[ta_1].h][ta[ta_1].x+i]='';
}
ta[ta_1].h--;
count_ta_1(ta_1);
system("cls");
//system("clear");
for(i=0;i<7+n;i++)
printf("%s\n",hnt[i]);
printf("%s",hnt[17]);
printf("\n\n从%c塔移动一个盘到%c塔\n",ta_1+65,ta_3+65);
printf("\n步数:
%d\n\n",sum);
if(computerorpeople==2)
system("pause");
else
for(i=0;i<200000*speed;i++);
}
3.1.3塔盘移动规律的定义
voidhanoi(intta_1,intta_2,intta_3,intm)//递归,ta_1/ta_2/ta_3分别为3座塔的代号,m为盘子数
{
if(m==1)
move(ta_1,ta_3);//如果盘子为1,将这个盘子从塔座A移动到塔座C
else
{
hanoi(ta_1,ta_3,ta_2,m-1);//将塔座A的前m-1个盘子移到塔座B
move(ta_1,ta_3);//将塔座A的第m个盘子移到塔座C
hanoi(ta_2,ta_1,ta_3,m-1);//将塔座B的m-1个盘子移到塔座C
}
}
3.1.4主函数main()
voidmain()
{
inti;
printf("请输入汉诺塔的高度(范围1->10):
");
scanf("%d",&n);
printf("请选择:
输入1由电脑自动控制;\n");
printf("输入2由人控制。
\n");
printf("请输入:
");
scanf("%d",&computerorpeople);
if(computerorpeople!
=1&&computerorpeople!
=2)
computerorpeople=1;
if(computerorpeople==1)
{
printf("请输入移动盘的速度(例如:
输入1000则代表1秒):
");
scanf("%d",&speed);
}
if(n<1||n>10)
n=10;
ta[0].h=n;
system("cls");//执行dos下的清屏命令
//system("clear");
for(i=0;i<7+n;i++)
printf("%s\n",hnt[i]);
printf("%s\n\n",hnt[17]);
system("pause");
hanoi(0,1,2,n);
if(computerorpeople==1)
system("pause");
}
4.系统调试
(1)程序编写过程中对文件调用不熟悉,子函数调用不到位,根据题设条件不断改进才逐步完善。
(2)结构语句编写错误,不能准确把握在哪里终止,但通过书上的例题可以掌握。
(3)程序编写时容易出现一些小错误,比如没有分号、缺了大括号等等,需要编写完后仔细检查。
(4)程序运行虽然没有错误,不能达到想要的效果,这时就需要借鉴大家的意见,共同商讨最佳的答案。
5.运行结果
(1)有电脑自动控制的时候:
图5.1主菜单
(2)汉诺塔游戏界面:
图5.2汉诺塔界面
图5.3汉诺塔塔盘移动界面
(3)有人控制的时候:
图5.4塔盘移动有人控制选择菜单
图5.4汉诺塔塔盘移动有人控制界面1
图5.4汉诺塔塔盘移动有人控制界面2
图5.4汉诺塔塔盘移动有人控制界面3
(4)塔盘搬到C盘的界面:
图5.5塔盘搬到C盘的界面
6.心得体会
通过此次课程设计,使我更加扎实的掌握了有关数据结构迷宫方面的知识,在设计过程中虽然遇到了一些问题,但经过一次又一次的思考,一遍又一遍的检查终于找出了原因所在,也暴露出了前期我在这方面的知识欠缺和经验不足。
实践出真知,通过亲自动手制作,使我们掌握的知识不再是纸上谈兵。
过而能改,善莫大焉。
在课程设计过程中,我们不断发现错误,不断改正,不断领悟,不断获取。
最终的检测调试环节,本身就是在践行“过而能改,善莫大焉”的知行观。
这次课程设计终于顺利完成了,在设计中遇到了很多问题,最后在老师的指导下,终于游逆而解。
在今后社会的发展和学习实践过程中,一定要不懈努力,不能遇到问题就想到要退缩,一定要不厌其烦的发现问题所在,然后一一进行解决,只有这样,才能成功的做成想做的事,才能在今后的道路上劈荆斩棘,而不是知难而退,那样永远不可能收获成功,收获喜悦,也永远不可能得到社会及他人对你的认可!
课程设计诚然是一门专业课,给我很多专业知识以及专业技能上的提升,同时又是一门讲道课,一门辩思课,给了我许多道,给了我很多思,给了我莫大的空间。
同时,设计让我感触很深。
使我对抽象的理论有了具体的认识。
通过这次课程设计,我进一步熟悉了VC++6.0软件的使用。
我认为,在这学期的实验中,不仅培养了独立思考、动手操作的能力,在各种其它能力上也都有了提高。
更重要的是,在实验课上,我们学会了很多学习的方法。
而这是日后最实用的,真的是受益匪浅。
要面对社会的挑战,只有不断的学习、实践,再学习、再实践。
这对于我们的将来也有很大的帮助。
以后,不管有多苦,我想我们都能变苦为乐,找寻有趣的事情,发现其中珍贵的事情。
就像中国提倡的艰苦奋斗一样,我们都可以在实验结束之后变的更加成熟,会面对需要面对的事情。
回顾起此课程设计,至今我仍感慨颇多,从理论到实践,在这段日子里,可以说得是苦多于甜,但是可以学到很多很多的东西,同时不仅可以巩固了以前所学过的知识,而且学到了很多在书本上所没有学到过的知识。
通过这次课程设计使我懂得了理论与实际相结合是很重要的,只有理论知识是远远不够的,只有把所学的理论知识与实践相结合起来,从理论中得出结论,才能真正为社会服务,从而提高自己的实际动手能力和独立思考的能力。
在设计的过程中遇到问题,可以说得是困难重重,但可喜的是最终都得到了解决。
实验过程中,也对团队精神的进行了考察,让我们在合作起来更加默契,在成功后一起体会喜悦的心情。
果然是团结就是力量,只有互相之间默契融洽的配合才能换来最终完美的结果。
此次设计也让我明白了思路即出路,有什么不懂不明白的地方要及时请教或上网查询,只要认真钻研,动脑思考,动手实践,就没有弄不懂的知识,收获颇丰。
7.附录
7.1参考书目
数据结构教程/李春葆等编著.——3版.——北京:
清华大学出版,2009.3
7.2源程序
#include
#include
#include
#include
#include
structT
{
inth;//塔的高度
intx;//塔的第一个盘的x坐标,y坐标等于(7+n-塔的高度h)
intl;//塔的第一个盘的长度
}ta[3]={{10,15,2},{0,0,0},{0,0,0}};
charhnt[18][79]={
{""},
{""},
{""},
{"╔════════════════════════════════════╗"},
{"║║"},
{"║║"},
{"║║"},
{"║▆║"},
{"║▆▆║"},
{"║▆▆▆║"},
{"║▆▆▆▆║"},
{"║▆▆▆▆▆║"},
{"║▆▆▆▆▆▆║"},
{"║▆▆▆▆▆▆▆║"},
{"║▆▆▆▆▆▆▆▆║"},
{"║▆▆▆▆▆▆▆▆▆║"},
{"║▆▆▆▆▆▆▆▆▆▆║"},
{"╚════════════════════════════════════╝"}};
intn;
intsum=0;
intcomputerorpeople=1;
intspeed=0;
voidcount_ta_1(intta_1)
{
inti;
intj;
intk=0;
for(i=7;i<7+n;i++)
for(j=4+ta_1*24;j<28+ta_1*24;j++)
{
if(hnt[i][j]!
='')
{
for(;hnt[i][j+k]!
='';k++);
ta[ta_1].x=j;
ta[ta_1].l=k;
return;
}
}
}
voidmove(intta_1,intta_3)
{
inti;
sum++;
ta[ta_3].h++;
ta[ta_3].x=ta[ta_1].x+(ta_3-ta_1)*24;
ta[ta_3].l=ta[ta_1].l;
for(i=0;i{
hnt[7+n-ta[ta_3].h][ta[ta_3].x+i]=hnt[7+n-ta[ta_1].h][ta[ta_1].x+i];
hnt[7+n-ta[ta_1].h][ta[ta_1].x+i]='';
}
ta[ta_1].h--;
count_ta_1(ta_1);
system("cls");
//system("clear");
for(i=0;i<7+n;i++)
printf("%s\n",hnt[i]);
printf("%s",hnt[17]);
printf("\n\n从%c塔移动一个盘到%c塔\n",ta_1+65,ta_3+65);
printf("\n步数:
%d\n\n",sum);
if(computerorpeople==2)
system("pause");
else
for(i=0;i<200000*speed;i++);
}
voidhanoi(intta_1,intta_2,intta_3,intm)//递归,ta_1/ta_2/ta_3分别为3座塔的代号,m为盘子数
{
if(m==1)
move(ta_1,ta_3);//如果盘子为1,将这个盘子从塔座A移动到塔座C
else
{
hanoi(ta_1,ta_3,ta_2,m-1);//将塔座A的前m-1个盘子移到塔座B
move(ta_1,ta_3);//将塔座A的第m个盘子移到塔座C
hanoi(ta_2,ta_1,ta_3,m-1);//将塔座B的m-1个盘子移到塔座C
}
}
voidmain()
{
inti;
printf("请输入汉诺塔的高度(范围1->10):
");
scanf("%d",&n);
printf("请选择:
输入1由电脑自动控制;\n");
printf("输入2由人控制。
\n");
printf("请输入:
");
scanf("%d",&computerorpeople);
if(computerorpeople!
=1&&computerorpeople!
=2)
computerorpeople=1;
if(computerorpeople==1)
{
printf("请输入移动盘的速度(例如:
输入1000则代表1秒):
");
scanf("%d",&speed);
}
if(n<1||n>10)
n=10;
ta[0].h=n;
system("cls");//执行dos下的清屏命令
//system("clear");
for(i=0;i<7+n;i++)
printf("%s\n",hnt[i]);
printf("%s\n\n",hnt[17]);
system("pause");
hanoi(0,1,2,n);
if(computerorpeople==1)
system("pause");
}
8评分表
计算机与通信学院课程设计评分表
课题名称:
数据结构
项目
评价
设计方案的合理性与创造性
设计与调试结果
设计说明书的质量
答辩陈述与回答问题情况
课程设计周表现情况
综合成绩
教师签名:
日期: