重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
将以下内容全部复制到新建的源文件中:(本人自己写的,因为你那课本上的代码,没解释,书写不规范,很难理解清楚,所以我直接新写了一个完整的代码,附带详细说明)
成都创新互联主营唐县网站建设的网络公司,主营网站建设方案,成都app开发,唐县h5微信小程序开发搭建,唐县网站营销推广欢迎唐县等地区企业咨询
#include stdio.h
//汉诺塔x层塔从A塔整体搬到C塔,中间临时B塔。
//x层塔是从大到小往上叠放。每次移动只能移动一层塔。并且在移动过程中必须保证小层在上边
//借助B塔可以将x层塔全部从A搬到C上,并且符合要求(在移动过程中大的那块在下边,小的那块在上边)
int main()
{
void tower(int x,char a,char b,char c); //声明函数
int x=5,a='A',b='B',c='C'; //x表示有5层塔,具体要多少层自己修改这个值。abc分别表示ABC塔。
tower(x,a,b,c); //x层塔从a移动到c的全过程,主程序只有这条有效语句
return 0;
}
//以下是tower函数的定义
//参数解析:x层塔放在a上,b是中间塔,c是目标塔。即x层塔要从a搬到c上。
//此函数实现x层塔从a整体转移到c上。以及这个过程是怎么搬的全部过程。
void tower(int x,char a,char b,char c)
{
if(x==1)printf("将%d从%c放到%c\n",x,a,c); //只有1层塔时,直接从a搬到c上。
else //不止1层塔,则先将x-1层塔从a按照规律搬到b上,再将最后一块从a搬到c上,最后再将b上的x-1层塔按照规律搬到c上。
{
tower(x-1,a,c,b); //先将x-1层塔从a按照规律搬到b上,注意参数b放在最后,因为放在最后的参数是准备搬过去的目标塔。
printf("将%d从%c放到%c\n",x,a,c); //将最后一块从a搬到c上
tower(x-1,b,a,c); //最后再将b上的x-1层塔按照规律搬到c上,注意参数b放在开头,因为x-1层是要从b上搬过去的。
}
}
解决汉诺塔的基本思想是先把n个盘子除了最下面的盘子以外的所有盘子从第一根柱子(初始柱子)移动到中间那个柱子上(辅助柱子),然后把最下面的盘子移动到最后一根柱子上(目标柱子)。最后把剩下的盘子移动到目标柱子上。这样,然而,完成第一步和第三步也同样是一个移动n-1个盘子的汉诺塔问题。于是,递归调用在这里不可避免。程序你已经写的很清楚,给你解释一下。现把你的程序画上行以便说明。
1 #include "stdio.h"
2 main()
3 {void hanoi(int,char,char,char); br/4 int m; br/5 printf("input the number of disks:"); br/6 scanf("%d",m); br/7 printf("The step to moving %d disks:\n",m); br/8 hanoi(m,'A','B','C'); br/9 }
10 void hanoi(int n,char a,char b,char c)
11 {//void move(char,char);
12 if(n==1) move(a,c);
13 else
14 {hanoi(n-1,a,c,b); br/15 move(a,c); br/16 hanoi(n-1,b,a,c); br/17 }
18 }
19 void move(char x,char y)
20 {printf("%c--%c\n",x,y); br/21 }
当m=4时,程序走到第8行,调用函数hanoi(int n,char a,char b,char c)。此时,实参把值传递给了形参,于是此时,n=4,a=A,b=B,c=C。我把第11行的void move(char,char); 注释掉了,应该知道这一句的意思。因为这一行虽然可以让程序更加完整,但是解释的时候加上它会很麻烦。程序走到第12行,因为此时n=4,而不等于1,程序直接走第13行。于是调用第14行的hanoi(n-1,a,c,b)。这是一个递归调用。此时,n=3,a=A,c=B,b=C。要清楚,A,B,C代表的意义。A代表初始柱子,B代表辅助柱子,C代表目标柱子。而a代表第一根柱子,b代表第二根柱子,c代表第三根柱子。这是不一样的。程序继续走,到12行时n依然不等于1。走到14行调用hanoi(n-1,a,c,b)。此时,n=2,a=A,c=C,b=B。程序再走,到12行时n依然不等于1,走到14行调用hanoi(n-1,a,c,b)。此时,n=1,a=A,c=B,b=C。程序走到12行时发现n=1,程序开始走15行。调用move(char x,char y)到20行时输出A--B。调用结束,回到上一个调用即n=2,a=A,c=C,b=B。程序回到第15行,输出 A--B。再走第16行,调用hanoi(n-1,b,a,c)。此时n=1,b=A,a=B,c=C。程序回到12行再调用19行输出B--C。调用结束,回到上一个调用n=3,a=A,c=B,b=C。程序走到15行,输出A--C,这时,第一根柱子上有一个盘子,第二根柱子上有一个盘子,第三根柱子上有两个盘子。再调用16行就可以完成把第三根柱子里的所有盘子都移动到第二根柱子上。这样。我们就完成了整体目标的第一步。把n个盘子除了最下面的盘子以外的所有盘子从第一根柱子(初始柱子)移动到中间那个柱子上(辅助柱子),调用完成后程序回到15行,此时n=3,a=A,c=B,b=C。15行时输出A--C,这时便完成了整体目标的第二步,最下面的盘子移动到最后一根柱子上(目标柱子)。再根据程序走到16行,经过跟14行类似的一系列的递归调用,我们就可以完成最终目标了。
#include graphics.h
struct H
{
int data[15];/*存放每个盘的代号*/
int top;/*每个塔的具体高度*/
}num[3];/*三个塔*/
void move(char x,char y,struct H num[3]);/*移动的具体过程*/
void hanoi(char x,char y,char z,int n,struct H num[3]);/*递归*/
void Init(void);/*初始化*/
void Close(void);/*图形关闭*/
int computer=1;/*自动控制与手动控制的标志*/
int speed=0;/*全局变量speed主要是演示过程的速度*/
void main(void)
{
Init();/*初始状态*/
Close();/*图形关闭*/
exit(0);
}
void Init(void)/*初始化*/
{
int gd=DETECT,gm;
int i,n,color;
clrscr();
printf("please input n(n=10): ");/*输入要演示的盘子数*/
scanf("%d",n);
printf("Please input 1 or 2:\n1点抗 puter 2.people\n");
scanf("%d",i);
if(i==2)/*选择手动控制标志为0*/
computer=0;
if(n1||n10)
n=10;/*越界的话n当10处理*/
if(computer)/*如果是自动控制的话输入速度*/
{
printf("please input speed: ");/*输入速度*/
scanf("%d",speed);
}
initgraph(gd,gm,"c:\\tc");
cleardevice();
for(i=0;i3;i++)
num[i].top=-1;/*三个地方的高度开始都为-1*/
for(i=0;in;i++)/*画一开始的塔座A上的盘子*/
{
num[0].top++;/*栈的高度加1*/
num[0].data[num[0].top]=i; /*最大的盘子代号为0,依次为1,2,…n-1*/
color=num[0].data[num[0].top]+1;/*盘子的颜色代码为栈顶盘子代号加1*/
setfillstyle(SOLID_FILL,color);
bar(100-(33-3*num[0].data[num[0].top]),400-20*i-8,100+
(33-3*num[0].data[num[0].top]),400-20*i+8); /*画矩形*/
}
setcolor(YELLOW);
outtextxy(180,450,"any key to continue");
settextstyle(0,0,2);
outtextxy(90,420,"A"); /*塔座标志*/
outtextxy(240,420,"B");
outtextxy(390,420,"C");
getch();/*接收字符后就执行递归操作*/
hanoi('a','b','c',n,num);
}
void move(char x,char y,struct H num[3])/*移动的具体过程*/
{
int i;
char num1[3],num2[3];
sprintf(num1,"%c",x-32);/*将小写变成大写,并转换成字符串输出*/
sprintf(num2,"%c",y-32);
setfillstyle(SOLID_FILL,BLACK);/*把原来的地方移去涂黑*/
bar(0,0,640,60);
setcolor(RED);
outtextxy(150,30,num1);/*输出移动过程*/
outtextxy(200,30,"---");
outtextxy(310,30,num2);
settextstyle(0,0,2);
setfillstyle(SOLID_FILL,BLACK);/*把原来的地方移去涂黑*/
bar(100+150*(x-97)-(33-3*num[x-97].data[num[x-97].top]),
400-20*num[x-97].top-8,100+150*(x-97)+(33-3*
num[x-97].data[num[x-97].top]),400-20*num[x-97].top+8);
num[y-97].top++;/*入栈,目标点的top加1*/
num[y-97].data[num[y-97].top]=num[x-97].data[num[x-97].top];/*在目标点盘子的代号与源点盘子的代号相同*/
num[x-97].top--;/*出栈,原来地方的top减1*/
setfillstyle(SOLID_FILL,num[y-97].data[num[y-97].top]+1);/*盘子颜色代码是栈顶盘子代号加1*/
bar(100+150*(y-97)-(33-3*num[y-97].data[num[y-97].top]),
400-20*num[y-97].top-8,100+150*(y-97)+
(33-3*num[y-97].data[num[y-97].top]),400-20*num[y-97].top+8);
if(computer)/*自动控制就用delay*/
delay(speed);/*延时函数*/
else
getch();/*手动控制的话就自己按键盘来控制*/
}
void hanoi(char one,char two,char three,int n,struct H num[3])/*递归n为盘子数,num为堆栈*/
{
if(n==1)
move(one,three,num);/*如果盘子为1,将这个盘子从塔座A移动到塔座C*/
else
{
hanoi(one,three,two,n-1,num);/*将塔座A的前n-1个盘子移到塔座B*/
move(one,three,num);/*将塔座A的第n个盘子移到塔座C*/
hanoi(two,one,three,n-1,num); /*将塔座B的n-1个盘子移到塔座C*/
}
}
void Close(void)/*图形关闭*/
{
getch();
closegraph();
}