1. 汉诺塔问题 来个好心人吧!!!
呵呵,这样不好理解的话,我们把变量换个名称吧。
void solve(int disks,int source,int temp,int destination)
{
if(disks==1)
printf("%d---->%d\n",source,destination);
else
solve(disks-1,source,destination,temp)
printf("%d-->%d\n",source,destination);
solve(disks-1,temp,source,destination)
}
disks表示圆盘的个数,source表示所有盘子原来在的那根柱子(第一根), 而destination表示要移动到目标的那根柱子(第三根),temp则表示第二根柱子,是用来临时存放圆盘的.
递归的过程不是分为三个小过程么?
1.从1号柱子source移动n-1个圆盘到2号柱子temp,用3号柱子做临时存放。
根据这句话的理解,可以写成这样
solve(disks-1,source,destination,temp)
为什么呢?
看函数声明吧~
void solve(int disks,int source,int temp,int destination)
前面说了,source表示原来盘子在的位置,temp表示临时存放盘子的位置,destination表示最终要移动到的位置。
那么对第一句话的意思,就可以写出:
solve(disks-1,source,destination,temp); //(*)
把disks-1个圆盘从原来的柱子1号位置,要先移动到2号柱子的位置上,所以2号柱子此时是做为最终要移动到的位置,而3号柱子是暂时存放的。所以这时候的(*)号语句中的temp是最终要移动到的位置。而destination作为临时存放的柱子.
2 从1号柱子移动最后一个圆盘到3号柱子上
那么很容易得出
printf("%d-----%d",source,destination);
3 从2号柱子移动n-1个圆盘到3号柱子,用1号柱子做临时存放.
那么也就是
solve(disks-1,temp,source,destination);
这时候,因为disks-1个圆盘在2号柱子上,所以暂时作为“原始柱子“,以1号柱子临时存放,1号柱子在开始时,就是source。而最终要移动到destination上去。
所以是这样写的
如果disks==1的时候,也就是说这时候只有一个盘。那么就可以直接的把盘子从source位置直接移动到destination位置上。不需要调用递归了。
2. 用C语言编汉诺塔游戏要有图形
Program Hanoi(input,output);
uses
crt;
type
a3=array[1..3] of byte;
var
n :byte;
Col,Flag:a3;
(* print a disk size is n on (x,y) *)
Procere Disk(x,y,n:byte);
var
i:byte;
Begin
for i:=0 to n do
begin
gotoxy(x+i,y);write('?);
gotoxy(x-i,y);write('?);
gotoxy(80,25);
end;
end;
(* a sound procere when move a disk *)
Procere Sing;
var
i,freq:integer;
Begin
Randomize;
for i:=1 to 10 do
begin
freq:=Random(2900)+100;
Sound(freq); Delay(20000);
NoSound;
end;
end;
(* clear a disk size is n on (x,y) *)
Procere ClrDisk(x,y,n:byte);
var
i:byte;
Begin
for i:=n downto 0 do
begin
gotoxy(x+i,y);write(' ');
gotoxy(x-i,y);write(' ');
end;
end;
(* initiate procere *)
Procere Initiate;
var
i:byte;
Begin
clrscr;
repeat { input n }
gotoxy(5,5);
write('输入汉锘塔的层数<1髇?1>:');
ClrEol;read(n);
until (0<n) and (n<12);
clrscr; {version information}
gotoxy(28,1);
write('** ',n,'-Hanoi Problem **');
gotoxy(37,2);
write('1992.10 W.Y.Z');
for i:=8 to 19 do {three pointers }
begin
gotoxy(15,i);write('?);
gotoxy(40,i);write('?);
gotoxy(65,i);write('?);
end;
for i:=1 to 80 do { the bottom }
begin
gotoxy(i,20);write('?);
end;
{ print A,B,C }
gotoxy(15,21);write('A');
gotoxy(40,21);write('B');
gotoxy(65,21);write('C');
for i:=n downto 1 do {n disks }
Disk(15,19-n+i,i-1);
{ initiate array Col[3],Flag[3] }
Col[1]:=15; Col[2]:=40; Col[3]:=65;
Flag[1]:=n+1; Flag[2]:=1; Flag[3]:=1;
{ some informations }
gotoxy(5,24);
write('Press spacebar to begin...');
repeat until ReadKey<>'';
gotoxy(5,24);ClrEol;
gotoxy(5,24);ClrEol;
write('Press any key to break.');
end;
(* move a disk FROM from TO too *)
Procere Move(m,from,too:byte);
var
x1,y1,x2,y2,n,step:byte;
Begin
x1:=Col[from]; y1:=20-Flag[from]+1;
x2:=Col[too] ; y2:=20-Flag[too];
step:=too-from; n:=m-1;
repeat { up }
ClrDisk(x1,y1,n);
if y1>=8 then begin gotoxy(x1,y1);write('?); end;
dec(y1);
Disk(x1,y1,n);Delay(10000);
until y1=5;
dec(Flag[from]);
repeat { shift }
ClrDisk(x1,5,n);
inc(x1,step);
Disk(x1,5,n);Delay(10000);
until x1=x2;
repeat { down }
ClrDisk(x2,y1,n);
if y1>=8 then begin gotoxy(x1,y1);write('?); end;
inc(y1);
Disk(x2,y1,n);Delay(10000);
until y1=y2;
inc(Flag[too]);
(* Sing; *)
if KeyPressed then Halt(0);
end;
(* n Hanoi Problem *)
procere N_Hanoi(n,a,b,c:byte);
Begin
if n=1 then Move(1,a,c)
else begin
N_Hanoi(n-1,a,c,b);
Move(n,a,c);
N_Hanoi(n-1,b,a,c);
end;
end;
(* print end information of this program *)
Procere Final;
Begin
gotoxy(5,24);ClrEol;
write('I have moved all disks !');
gotoxy(5,25);
write('Press spacebar to end.');
repeat until ReadKey<>'';
end;
Begin
Initiate;
N_Hanoi(n,1,2,3);
Final;
End.
3. 哪位大佬有python汉诺塔的教程
学到递归的时候有个汉诺塔的练习,汉诺塔应该是学习计算机递归算法的经典入门案例了,所以本人觉得可以写篇博客来表达一下自己的见解。这markdown编辑器还不怎么会用,可能写的有点格式有点丑啦,各位看官多多见谅.
网上找了一张汉诺塔的图片,汉诺塔就是利用用中间的柱子把最左边的柱子上的圆盘依次从大到小叠上去,说白了就是c要跟原来的a一样
童鞋们理解了汉诺塔的递归算法原理后,可以写个程序来试试,这里只是学到Python的递归所以用了Python,童鞋们可以用其他语言实现,汉诺塔确实能帮助理解递归原理,递归在程序设计中的重要性不言而喻啦!
4. 汉诺塔流程图
你好!
汉诺塔流程图:
voidmove(int,char,char,char);/*声明函数,告诉系统我随后要定义一个函数,他不对其中参数进行检查,所以可以省略参数,一般只写类型,表示有多少个什么类型的参数,便于自己理解*/
main()
{intn;
printf("请输入盘数n=");
scanf("%d",&n);
printf("在3根柱子上移%d只盘的步骤为: ",n);
move(n,'a','b','c');}/*函数调用,用a,b,c代表3跟柱子,把盘子数,柱子代码传给函数*/
voidmove(intm,charp,charq,charr)//定义函数
{if(m==1)
{printf("[%d]move1#from%cto%c ",step,p,r);
step=step+1;}
else{move(m-1,p,r,q);//调用本身函数,进行递归A
printf("[%d]move%d#from%cto%c ",step,m,p,r);
step=step+1;
move(m-1,q,p,r);//再次调用B
}
getch();}
递归其实是嵌套调用,
所谓嵌套调用,就是在一个函数里调用另一个函数,
main函数不能被调用的,
所以递归就是有限次的嵌套调用本身函数
每次调用,系统都会重新分配内存,
返回时就返回上次调用他的那块内存中的调用函数处,
这样理解应该很简单了
汉诺塔流程图解析:
这里面的递归涉及一个汉诺塔的算法问题,具体讲明白的话有点麻烦,总体思路是假设盘子全在a柱上,想放到c上
第N个人就想要是有人搬动其他N-1个盘子到b,那他只要搬一次从a到c就可以,在让那个人把N-1个盘子放到c上
第N-1那个人就想要是有人搬动其他N-2个盘子到c,他只要搬动一次从a到b就可以,在让那个人把N-2个盘子放到b上
....
第1个人就直接把盘子从a到c
这样形成递归
我在俩处调用标记了A,B,我写出步踌,你看看.
假设3个盘子
A函数相当于双重循环中的外层循环
B函数相当于双重循环中的内层循环
1,主函数调用,p=a,q=b,r=c,m=3,运行A,调用本身(A第一次调用)传入p,r,q(a,c,b)注意调用函数中p,r,q排列
2,被调函数是用p,q,r的顺序接收传入的p,r,q.p=a,q=c,r=b,m=2,执行A,调用本身(A第二次调用)调用传入p,r,q(a,b,c)
3,p=a,q=b,r=c,m=1,执行if,输出a->c,返回A第二次调用
4,本次函数中p=a,q=c,r=b,m=2,向下执行,输出a->b,执行B,调用本身(B第一次调用),传入q,p,r(c,a,b),m=1
5,p=c,q=a,r=b,m=1,执行if,输出c->b,返回B第一次调用
6,向下执行,执行完毕,返回A第一次调用
7,本次函数中p=a,q=b,r=c,m=3,向下执行,输出a->c,执行B,调用本身(B第一次调用),传入q,p,r(b,a,c),m=2
8,p=b,q=a,r=c,m=2,执行A,调用本身(A'第一次调用,注意是B函数调用中再次调用A)传入p,r,q(b,c,a)
9,p=b,q=c,r=a,m=1,执行if,输出b->a,返回A'第一次调用
10,本次函数中p=b,q=a,r=c,m=2向下执行,输出b->c,执行B,调用本身(B'的第一次调用,注意是B函数中再次调用B)传入q,p,r(a,b,c),m=1
11,p=a,q=b,r=c,m=1,执行if,输出a->c返回B'第一次调用
12,向下执行,执行完毕,返回B第一次调用
13,向下执行,执行完毕,返回主函数
仔细分析每次调用时当前变量p,q,r中所代表的a,b,c,每次调用时,p,q,r都是新的变量
我看了你的问题,估计你把调用函数中的p,q,r变量与被调函数中p,q,r变量搞混了
/*
4,向下执行,执行B,调用本身(B第一次调用),由于本次函数中p=a,q=c,r=b,m=2,先输出a->b,再传入q=c,p=a,r=b,m=1
这里不是[4]move3#fromatoc吗
*/
注意调用传入的顺序是q,p,r,传入的值是c,a,b的顺序,被调函数中是拿p,q,r的顺序在接收,所以被调函数中值的顺序就该是p=c,q=a,r=b,执行if就输出c->b
补充:流程图步骤画了好久额,有什么疑问发我邮箱[email protected]
5. 急!Hanoi塔问题的动画演示
/*5. 源程序*/
/********hanoi.c*********/
#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.computer 2.people\n");
scanf("%d",&i);
if(i==2)/*选择手动控制标志为0*/
computer=0;
if(n<1||n>10)
n=10;/*越界的话n当10处理*/
if(computer)/*如果是自动控制的话输入速度*/
{
printf("please input speed: ");/*输入速度*/
scanf("%d",&speed);
}
initgraph(&gd,&gm,"c:\\tc");
cleardevice();
for(i=0;i<3;i++)
num[i].top=-1;/*三个地方的高度开始都为-1*/
for(i=0;i<n;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();
}
上面的不是我写的,你比较幸运,刚好我这里有现成的
这里共有包括冒泡法排序等23个演示程序
6. 汉诺塔的问题:4个柱子,如果塔的个数变位a,b,c,d四个,现要将n个圆盘从a全部移到d,移动规则不变
C语言:
#include<iostream>
usingnamespacestd;
voidmove(chara,charb){
cout<<a<<"----->"<<b<<endl;
voidhannuo(intn,chara,charb,charc,chard){
if(1==n){
move(a,d);
elseif(2==n){
move(a,b);
move(a,d);
move(b,d);
else{
hannuo(n-2,a,c,d,b);
move(a,c);
move(a,d);
move(c,d);
hannuo(n-2,b,c,a,d);
intmain(){
chara='a',b='b',c='c',d='d';
inti;
cout<<"请输入盘子的个数";
while(cin>>i){
hannuo(i,a,b,c,d);
return0;
(6)汉诺塔怎么画简单图片扩展阅读:
解题思路:
如a,b,c,d四柱,要把a柱第n个盘移到目标柱子(d柱),先把上层分两为两部份,上半部分移到b柱,下半部分移到c柱,再把第n盘移到目标柱子,然后,c柱盘子再移到目标柱子,再把b柱盘子移到目标柱子。
细节地方:上半部分移到b柱时,它的中间变量柱子是有二选一的。而下半部分移到c柱时,它的中间变量柱子只有一个(因为一个柱子已被上半部份占了),b,c也移到目标柱子时同理。
7. hanoi塔里面不懂的地方。望解答。
if(n==1)①
move(one,three);
else
{
hanoi(n-1,one,three,two);②
move(one,three);③
hanoi(n-1,two,one,three);④//你的程序这里似乎是写错的。
}
给你画了个图看递归运行的过程。虽然还是不抱太大希望能讲明白……
递归跟数学上的数学归纳法类似。
n=1的时候,hanoi(1,A,B,C)能成功将一个盘子从A经过B移到C.
假设n-1时,hanoi(n-1,A,B,C)能成功将n-1个盘子从A经过B移到C.
那么,n时,hanoi(n,A,B,C)首先调用hanoi(n-1,A,B,C),
将上面n-1个盘子从A经过C移到B上(这一点在假设里已经满足)
也就是hanoi(n-1,one,three,two);②;
然后将最下面一个盘子从A移到C,也就是move(one,three);③
最后将刚才那n-1个盘子从B经过A移到C上,
也就是hanoi(n-1,two,one,three);④,
这一点也是假设条件,也能成功。
所以得证,n为任意整数时,调用hanoi(n,A,B,C)就可以把n个盘子从A经过B运到C上去。
你要跟着程序把整个移动3个盘子的过程跟踪一遍就好懂了。如果还是不行,就找个身边的懂的人讲讲。
祝你成功~毕竟递归还是程序设计中很重要的一个部分。
8. 麻烦有了解汉诺塔问题的吗
/********hanoi.c*********/
#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);
getch();
}
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.computer 2.people\n");
scanf("%d",&i);
if(i==2)/*选择手动控制标志为0*/
computer=0;
if(n<1||n>10)
n=10;/*越界的话n当10处理*/
if(computer)/*如果是自动控制的话输入速度*/
{
printf("please input speed: ");/*输入速度*/
scanf("%d",&speed);
}
initgraph(&gd,&gm,"c:\\tc");
cleardevice();
for(i=0;i<3;i++)
num[i].top=-1;/*三个地方的高度开始都为-1*/
for(i=0;i<n;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();
}
这是递归的,
下面是非递归的,
#include <stdio.h>
#include <dos.h>
#include <stdio.h>
#define JISHU 1
#define OUSHU 2
#define MAX 9
#define LEFT -1
#define RIGHT 1
/* /* /* //////////////////////////////////////////////////////// */ */ */
void init(int plate, char far *p); /* 初始化图形 */
void move(int id,int type, char far *p); /* 移动板块 */
void power(int plate,long power_s[]); /* initialize the power_s[] */
void start(char far *p); /* 开始移动 */
int scan(int base, char far *p);
void draw (int base, int length, char far *p);
int plate=100; /* 这个板块的数量*/
int type=JISHU; /* 判断plate是奇数还是偶数 */
long power_s[MAX+1]={0}; /* 提前记录间隔数,以降低调用函数的损耗*/
int count = 0;
int base_1[31]={0};
int base_2[31]={0};
int base_3[31]={0};
int n_1=0,n_2=0,n_3=0;
int time;
void main(void)
{
char far *p;
union REGS r;
r.h.al=0x13;
r.h.ah=0;
int86(0x10,&r,&r) ;
p=(char far *)(0xa0000000l);
while(plate>MAX || plate<1)
{
printf("please input the number of the plate(1~%d)",MAX);
scanf("%d",&plate);
}
printf("please input the delay time(0~~~10000):");
scanf("%d",&time);
init(plate, p); /* 初始化图形 */
if(plate%2==0)
type=OUSHU;
else type=JISHU;
power(plate,power_s);
start(p); /* 开始移动 */
getchar();
}
/* /* /* ////////////////////////////////////////////////// */ */ */
void start(char far *p)
{
int temp[1024]; /* 把移动步骤放入temp中*/
long i=1; /* 循环变量 */
long n=1; /* 首次将要移动的盘子 */
for(n=1;n<=plate;n++)
{
for(i=power_s[n-1]+1;i<power_s[plate]+1;)/* 第n个盘子将在第i次移动 */
{
temp[i]=n;
i=i+power_s[n]+1;
}
}
for(i=1;i<=power_s[plate];i++) /* 开始移动*/
{
move(temp[i],type,p);
}
}
/* /* /////////////////////////////// */ */
/* */
/* */
/* 以下为图像处理部分 */
/* */
/* /* /////////////////////////////// */ */
void init(int plate, char far *p)
{
int i=0;
int k;
system("cls");
for (;i<=200; i++) /* 1 */
{
*(p+50+320+320*i)=3;
} /* 2 */
for (i=0;i<=200; i++)
{
*(p+160+320+320*i)=3;
}
for (i=0;i<=200; i++) /* 3 */
{
*(p+265+320+320*i)=3;
}
for (k=0; k<plate; k++)
{
for (i=k; i<=100-k; i++)
{
*(p+i+320*(195-4*k))=1;
}
delay (time);
}
k=0;
for (i=plate;i>=1;i--)
{
base_1[k++] = i;
}
n_1 = k-1;
}
/* /* /* /////////////////////////////////////////////////////// */ */ */
int scan(int base, char far *p)
{
int x = 0;
int y = 0;
int x_l;
int length = 0;
if (base == 1)
x = 49;
if (base == 2)
x = 159;
if (base == 3)
x = 264;
for (y=0; y<=199; y++) /*scan the y*/
{
if (*(p+x+320*y) == 1)
break;
}
x_l = x-49; /*scan the length*/
for (;;)
{
if (*(p+x_l+320*y)==1)
break;
x_l++;
}
for (;;)
{
if (*(p+x_l+320*y)!=0)
{
*(p+x_l+320*y)=0;
delay (time);
x_l++;
length++;
}
else
break;
}
length--;
return length;
}
void draw (int base, int length, char far *p)
{
int x = 0;
int y = 0;
int x_l;
if (base == 1)
x = 49;
if (base == 2)
x = 159;
if (base == 3)
x = 264;
for (y=0; y<=200; y++) /*scan the y*/
{
if (*(p+x+320*y) == 1)
break;
}
y-=4;
x_l = x-49+(100-length)/2;
for (;length>=0;length--)
{
*(p+x_l+320*y)=1;
x_l++;
delay (time);
}
}
void move(int id, int type, char far *p)
{
int base;
int length;
int direct;
if(type==OUSHU)
{
if(id % 2==0)
direct=LEFT;
else
direct=RIGHT;
}
else
{
if(id % 2==0)
direct=RIGHT;
else
direct=LEFT;
}
if (id == base_1[n_1]) /*which base has the id plate*/
base = 1;
else if (id == base_2[n_2])
base = 2;
else if (id == base_3[n_3])
base = 3;
else
{
printf ("Guozhen is GuaWaZi\n");
getchar();
exit (0);
}
length = scan (base, p); /*scan the length of the id plate and disdraw the plate*/
if (base == 1) /*清理堆栈*/
n_1--;
else if (base == 2)
n_2--;
else
n_3--;
if (direct == LEFT)
{
if (base == 1)
base = 3;
else
base --;
}
else
{
if (base == 3)
base = 1;
else
base ++;
}
draw (base, length, p); /*画盘子*/
if (base == 1) /*增加堆栈*/
{
n_1++;
base_1[n_1]=id;
}
else if (base == 2)
{
n_2++;
base_2[n_2]=id;
}
else
{
n_3++;
base_3[n_3]=id;
}
count++;
printf ("\b\b\b\b\b\b%d",count);
}
void power(int plate,long power_s[])
{
int i=1;
for(i=1;i<=plate;i++)
{
power_s[i]=(power_s[i-1]+1)*2-1;
}
}
9. 汉诺塔问题
刚上大学的时候学c语言,觉得最精彩的也就是汉诺塔问题,但是最糊涂的也是这个问题,因为程序的注释中是“move(n-1,a,c,b)--把n-1个盘子从a柱移动至b柱(借助c柱)”,这个注释有几个问题,1.程序把n中的哪些(n-1)个盘子从a柱移动至b柱?2.这个过程中如何借助c柱?程序是没有问题,这个注释感觉太大而化之了,真感觉像领导在说话一样,具体做,肯定要解决,要有落脚点,其实程序也是一步一步执行的,绝对不会推卸责任,只是编书的这样解释更朦胧,美其名曰“递归”,这几天花了两天时间,终于明白了,其实程序执行是一个嵌套和参数变化的过程,比如说三层,插入图片算了,不然打字麻烦的很。我简单说明一下,程序是三个部分,第一步执行{move(n-1,a,c,b),第二步执行输出a,c(从参数a对应的数字移动到参数c对应的数字上,参数a和c在程序中是变化的),第三部执行move(n-1,b,a,c),每个个不是n=1的都是这么循环,大循环里有小循环,具体好好看我画的图,不明白就问qq:99769975。另外,0分是不是有点太不够意思了。