汉诺塔问题解决及游戏方案
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
汉诺塔问题的解决及游戏设计
班级:数学与应用数学0901
姓名:何文坤黄骏
指导老师:王玉英
随着时代的不断发展进步,计算机已经融入我们的日常生活。
很多时候,很多的问题想通过人的手来亲自解决已变得十分困难了,这时我们就要运用计算机来帮我们解决这些复杂的问题。
汉诺塔问题就是这类较复杂的问题。
汉诺塔游戏规则:有三根针A,B,C。
A针上有n个盘子,盘子大小不等,大的在下,小的在上。
要求把这n个盘子移到C针,在移动过程中可以借助B针,每次只允许移动一个盘子,且在移动过程中在三根针上的盘子都保持大盘在下,小盘在上。
此次,我们通过Visual
C++软件运用递归算法来解决汉诺塔问题。
程序运行后会出现一个界面,界面上有各种操作提示,按照提示进行各种操作后会得到汉诺塔游戏的运行过程及结果。
关键词:汉诺塔;Visual C++;递归算法;
问题描述------------------------------------------------------------------------------1开发平台------------------------------------------------------------------------------2变量命名规则------------------------------------------------------------------------3程序中主要类或函数的描述------------------------------------------------------4程序流程-----------------------------------------------------------------------------------------6设计难点及难点处理---------------------------------------------------------------7运行结果及结果分析---------------------------------------------------------------8程序需要完善的地方---------------------------------------------------------------10自己的心得体会---------------------------------------------------------------------11
一、问题描述
汉诺塔<又称河内塔)问题是起源于印度的一个古老的传说。
开天辟地的神勃拉玛在一个庙里留下了三根金刚石柱,第一根上面套了64个圆的金片,大的在下,小的在上。
庙里的众僧不倦地把他们一个个的从这根柱搬到另一根柱上,规定可以利用中间的一根柱作为帮助,但每次只能般一个,而且大的不能放在小的上面。
这是一个著名的问题。
由于条件是一次只能移动一个盘,且不允许大盘放在小盘上面,所以64个盘的移动次数是18446744073709551615次。
这是一个天文数字,若每一微秒可能计算一次移动,那么也需要几乎一百万年。
我们仅能找出问题的解决方法并解决较小N值时的汉诺塔,但很难用计算机解决64层的汉诺塔。
后来,这个传说就演变成汉诺塔游戏:
1.有三根针A,B,C,A针上有n个圆盘。
2.每次移动一个圆盘,小的只能叠在大的上面。
3.把所有圆盘出从A针上全部移动到C针上,移动过程中可以利用中间的B
针作为帮助。
汉诺塔问题也是程序设计中的经典递归问题:
将n个盘从A针上全部移动到C针可以分解为下面3个步骤
(1)将A上n-1个盘移到B针上<借助C针)。
(2)把A针上剩下的一个盘子移到C针上。
(3)将n-1个盘子从B针移动到C针上<借助A针)。
二、开发平台
此次课程设计运用到的开发平台有Windows XP和Visual C++。
通过C++语言编程来实现较小n值汉诺塔问题的解决。
三、变量命名规则
四、程序中主要类或函数的描述
五、程序流程
六、设计难点及难点处理
七、运行结果及结果分析
程序的运行结果如下:
第一步,输入盘的个数n<范围为1—>10)运行结果如图1所示:
图1
第2步,选择菜单中的1,电脑自动控制和选择菜单中的2,由人控制,运行结果如图2所示:
图2
第3步,输入盘的移动速度,运行结果如图3所示:
图3
第4步,输出运行结果。
运行过程和结果如图4,5所示:
图4
图5
第5步,输入p,判断是否继续游戏运行,运行结果如图6所示: 图6
第6步,若继续游戏,运行结果如图7,再次循环:
图7
结果分析:
在做汉诺塔问题时,最大的问题就是如何来移动盘子,而且要满足各种限制条件。
此次,我们将盘子抽象成一个数组中的具体元素,通过改变数组中元素的位置来实现盘子的移动。
我们知道,改变数组中的元素位置是很容易实现的,这样就将负责的问题简单化了。
再者,为实现游戏的连续性,我们在程序中加入了一个循环语句来实现此功能。
可单单加入循环还不能实现这功能,再继续进行下一次游戏是,需要将上次的游戏运行结果进行初始化,若不初始化,下次的运行结果将会是在上次运行结果的基础上再将程序运行一遍,就会出现错误。
所以在为了得到此结果,需要注意很多容易疏忽的小细节。
八、程序需要完善的地方
九、自己的心得体会
一个多礼拜里,我们有过不少的疑惑和惊喜,也有过唇枪舌剑的争论和相互鼓励的安慰。
我们经历了很多,同时也收获了很多。
经过这次课程设计,我不仅学到了很多知识和技能,更重要的是锻炼了我们如何运用所学的知识去解决实际问题的能力。
C++语言课程设计和现代计算机技术相结合,是对我在本阶段学完理论知识课程后对自己该方面能力的一次很好检验。
从开始的算法思路到程序运行调试后得到了运行结果界面以及令人兴奋的可行程序,都是一次很好的学习和锻炼过程。
使我们巩固了所学的理论知识,培养了我灵活运用和知识组合及技能来分析和解决实际问题的能力。
同时还提高了我对C++语言的兴趣。
总之,在这一次C++语言课程设计中我获得了如下收获:
1.对实验原理有了更深刻的理解
2.对该理论在实际应用中有了深刻的理解
3.激发了学习的积极性
十、参考文献
[1]申惠芳,基于VC++语言的四针汉诺塔游戏的设计与算法研究,山东,
科技信息,2018年32期;
[2]黄维通,VC++面向对象与可视化程序设计[M],北京:清华大学出版社;
[3]孙东宁,汉诺塔问题研究,吉林,考试周刊,2018年28期;
[4]郑莉,董渊,何江舟,C++程序语言设计[M]<第4版),北京:清华大学出版社,2018;
[5]常跃,汉诺(Hanoi>塔递归算法的教案研究,云南,云南电大学报,2005年1期。
附录<程序)
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
#include<string.h>
#include<math.h>
#include<iostream.h>
struct T
{
int h。
//塔的高度
int x。
//塔的第一个盘的x坐标 ,y坐标等于(7+n-塔的高度h>
int l。
//塔的第一个盘的长度}ta[3]={{10,15,2},{0,0,0},{0,0,0}}。
char c[18][79],hnt[18][79]={
{" "},
{" 汉诺塔动画演示 "},
{" "},
{" ╔════════════════════════════════════╗"},
{" ║║"},
{" ║║"},
{" ║║"},
{" ║▆║"},
{" ║▆▆║"},
{" ║▆▆▆║"},
{" ║▆▆▆▆║"},
{" ║▆▆▆▆▆║"},
{" ║▆▆▆▆▆▆║"},
{" ║▆▆▆▆▆▆▆║"},
{" ║▆▆▆▆▆▆▆▆║"},
{" ║▆▆▆▆▆▆▆▆▆║"},
{" ║▆▆▆▆▆▆▆▆▆▆║"},
{" ╚════════════════════════════════════╝"}}。
int n。
int sum=0。
int computerorpeople=1。
int speed=0。
void count_ta_1(int ta_1>//重新计算塔的第一个盘的x坐标和塔的高度{
int i。
int j。
int k=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。
}
}
}
void move(int ta_1,int ta_3>
{
int i。
sum++。
ta[ta_3].h++。
ta[ta_3].x=ta[ta_1].x+(ta_3-ta_1>*24。
//每个塔之间相隔4
ta[ta_3].l=ta[ta_1].l。
for(i=0。
i<ta[ta_1].l。
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">。
for(i=0。
i<7+n。
i++>
cout<<hnt[i]<<endl。
cout<<hnt[17]。
cout<<endl<<endl<<"
从"<<char(ta_1+65><<"塔移动一个盘到"<<char(ta_3+65><<"塔"<<endl。
cout<<endl<<" 步数:"<<sum<<endl<<endl。
if(computerorpeople==2>
system("pause">。
else
for(i=0。
i<200000*speed。
i++>。
}
void hanoi(int ta_1,int ta_2,int ta_3,int m> //递归,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
}
}
void main(>
{
int i,b=1。
for(i=0。
i<18。
i++>
{
for(int j=0。
j<=78。
j++>
{
c[i][j]=hnt[i][j]。
}
}
while(b==1>
{
cout<<"请输入汉诺塔的高度<范围1->10):"。
cin>>n。
cout<<"请选择:输入1由电脑自动控制。
"<<endl。
cout<<" 输入2由人控制。
"<<endl。
cout<<"请输入:"。
cin>>computerorpeople。
if(computerorpeople!=1&&computerorpeople!=2>
computerorpeople=1。
if(computerorpeople==1>
{
cout<<"请输入移动盘的速度(例如:输入1000则代表1秒>:"。
cin>>speed。
}
if(n<1||n>10>
n=10。
ta[0].h=n。
system("cls">。
//清除屏幕
for(i=0。
i<7+n。
i++>
cout<<hnt[i]<<endl。
cout<<hnt[17]<<endl。
system("pause">。
//
system("pause">就是从程序里调用“pause”命令。
而“pause”这个系统命令的功能
很简单,就是在命令行上输出一行类似于“Press any key to exit”的字,等待用户按一个键,然后返回。
hanoi(0,1,2,n>。
if(computerorpeople==1>
system("pause">。
system("cls">。
for(i=0。
i<18。
i++>
{
for(int j=0。
j<=78。
j++>
{
hnt[i][j]=c[i][j]。
}
}
cout<<"是否继续游戏?是请按1,不是请按2"<<endl。
cin>>b。
sum=0。
ta[0].h=10。
ta[0].l=2。
ta[0].x=15。
for(i=1。
i<3。
i++>
{
ta[i].h=0。
ta[i].l=0。
ta[i].x=0。
}
}
}。