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分是不是有點太不夠意思了。