汉诺塔c语言代码:
void move(char start, char end)
{
printf("%c->%c ", start, end);
}
void Hanoi(int n, char start, char temp, char end)
{
if (n == 1)
{
move(start, end);
}
else
{
Hanoi(n - 1, start, end, temp);
move(start, end);
Hanoi(n - 1, temp, start, end);
}
}
int main()
{ Hanoi(4, 'A', 'B', 'C');
return 0;
}
逻辑:
首先看汉诺塔的逻辑,假如我们一共有5个盘子:
- 首先我们要将5个盘子移动到C上,则先将1~4盘子移到B上,再将5移到C上。
- 要将1~4盘子移到B上,则先将1~3盘子移到C上,再将4移到B上。
- 要将1~3盘子移到C上,则先将1~2盘子移到B上,再将3移到C上。
- 要将1~2盘子移到B上,则先将1号盘子移到C上,再将3移到B上。
- 如何将1盘子移到C上?只剩一个盘子时,直接移动。
第一次输出:A->C
-
第一步将1移到C上,只有一个盘子直接移动:A->C。
第二次输出:A->B
第三次输出:C->B
2.将1、2移动到B上,则先将A上的2挪到B上,再将C上的1挪到B上:A->B C->B.
第四次输出:A->C
3.将1、2、3移动到C上,则先将A-3移到C上。输出A->C:
再将B上的1、2移动到C上,B为起始柱子,C为终点柱子,借助A,将1,2移到C上。
则先将B-1移到A上,再将B-2移到C上:
第五次输出:B->A
第六次输出:B->C
这时再将A-1放到C上,我们就完成了将1、2、3这三个盘子放到C上。
第七次输出:A->C
4.将1、2、3、4移动到B上。
对于A-4,只有一个盘,直接移动。
第八次输出:A->B
此时要将C-1、2、3移动到B上:
(1)要将C-1、2、3给B,得先将C-1、2给A。
(2)要将C-1、2给A,得先将C-1给B。
(2-1)先将C-1给B
第九次输出:C->B
(2-2)为了将1、2都放到A上,此时C-2移到A上,再将B-1移到A上:
第十次输出:C->A
第十一次输出:B->A
(1-1)此时,我们已经将1、2挪给了A,这时将C-3放到B上。
第十二次输出:C->B
再将A-1、2以C为中转柱移给B:
即A-1挪给C:
第十三次输出:A->C
再将A-2挪给B
第十四次输出:A->B
再将C上的1挪给B
第十五次输出:C->B
5.将1、2、3、4、5都移到C上。
此时我们已经完成了将1、2、3、4都移动到B上。
现在,我们将5号盘移到C上:
第十六次输出:A->C
此时我们要将B-1、2、3、4都移到C上。
(I)要将B-1、2、3、4都移到C上,则先将B-1、2、3移到A上
(1)要将B-1、2、3都移到A上,则先将B-1、2先移到C上
(2)要将B-1、2都移到C上,则先将B-1先移到A上
结果:
第十七次输出:B->A 1
第十八次输出:B->C 2
第十九次输出:A->C 1
第二十次输出:B->A 3
第二十一次输出:C->B 1
第二十二次输出:C->A 2
第二十三次输出:B->A 1
(II)此时将B-4放到C上:
第二十四次输出:B->C 4
此时我们已经将1、2、3移到了A上。这时我们想将A-1、2、3都移到C上,则B作为中转柱子。
(1)若要将A-1、2、3都移到C上,则先将A-1、2挪到B上。
(2)要将A-1、2都挪到B上,则先将A-1挪到C上。
此过程跟上面一样,这里不再继续叙述。
第二十五次输出:A->C 1
第二十六次输出:A->B 2
第二十七次输出:C->B 1
此时1、2盘都在B上
第二十八次输出:A->C 3
这里将3号盘子放到C上
第二十九次输出:B->A 1
第三十次输出: B->C 2
第三十一次输出: A->C 1
汉诺塔逻辑概括
至此,汉诺塔移动盘子的逻辑我们已经讲述清楚了。
概括以下就是:
一、
假设A有n个盘子要移到C,则将n-1个盘子先移到B,再将最底下那个(n)号盘子移给C。
如何将A上n-1个盘子移动给B呢?
则先将上面n-2个盘子先移给C,再将最底下那个(n-1)号盘子移动给B。
如何将A上n-2个盘子移动给C呢?
则先将上面n-3个盘子移动给B,再将最底下那个(n-2)号盘子移动给C。
......
依次类推
直到剩下最顶上一个盘子,就可以直接移动。
代码输出对照
此时我们来对照以下代码的运行输出和我们的假设输出是否相同:
代码如下:
void move(char start, char end)
{
printf("%c->%c \n", start, end);
}
void Hanoi(int n, char start, char temp, char end)
{
if (n == 1)
{
move(start, end);
}
else
{
Hanoi(n - 1, start, end, temp);
move(start, end);
Hanoi(n - 1, temp, start, end);
}
}
int main()
{ Hanoi(5, 'A', 'B', 'C');
return 0;
}
运行结果如下:
程序逻辑
现在我们再来看看程序的运行逻辑,为了方便讲述,我们假设有3个盘子。
首先我们在main函数中向Hanoi函数传入参数,即盘子个数,以及三个柱子:
int main()
{ Hanoi(3, 'A', 'B', 'C');
return 0;
}
我们将A柱子作为start开始柱,将B柱子作为temp中转柱子,将C柱子作为end终点柱子。
void Hanoi(int n, char start, char temp, char end)
{
if (n == 1)
{
move(start, end);
}
else
{
Hanoi(n - 1, start, end, temp);
move(start, end);
Hanoi(n - 1, temp, start, end);
}
要将1、2、3这三个盘子放到C中,首先1、2要放入B中。而若要将A-1、2放入B中,就要将C作为中转柱。
第一次输出为A->C 1
第二次输出为A->B 2
第三次输出为C->B 1
此时B就成为了终点柱子,C成为了中转柱子。
也就是下图的黄色语句:
执行完黄色语句后,汉诺塔变成下面这样:
此时A只剩下一个盘子,执行第一条Hanoi语句下面的move函数调用语句,将A上的3号盘子移动到B上:
第四次输出为A->C 3
此时,我要将tempB上的n-1(2)个盘子放到C上,我就要借助A柱子,先将n-2个盘子放到A上。
此时B成了开始start柱,A成了我们的中转柱子,而C是我们的目标柱子。
来到第三条语句:
此处这条语句的四个参数分别是(2,B,A,C)
传入后,B为开始start柱,A为temp柱,C为end柱。n>1,进入else部分:
来到第一条语句Hanoi(n-1,start,end,temp),此时的参数为(1,B,C,A)。
由这条语句进入Hanoi函数后,B为开始start,C为中转temp,A为结束end。
此时来到if语句,n==1,进入move函数,B将1号盘子传给了A:
第五次输出B->A.
此时我们从第一条Hanoi函数语句出来,走到move函数语句。此时B还是start柱,A变回了temp柱,C变回了end柱。
此时我们来到move(start,end)语句。
这里就是将2号盘子放到C上。
第六次输出B->C.
接下来来到第三条语句:
这时这条语句的参数是(1,A,B,C)
这条语句执行,我们再进入Hanoi函数:
此时原先为temp的A变成了start,原先为start的B变为了temp。
此时n==1,进入if语句。
进入if语句后,执行move(start,end)。
即将A也就是start柱子上的1号盘,传给作为end的C柱。
第七次输出A->C.
至此,我们将全部的盘子都移动到了C上。
输出对照
这里我们检验我们逻辑的输出和程序的输出:
程序概括:
程序代码作用概括:
第一条hanoi语句的作用是将A上的n-1个盘子移到B中。
第二条语句move语句的作用是将A上最大的盘子即n号盘移到C中。
第三条语句Hanoi语句的作用是,将B看作开始start柱子,A为辅助temp柱子,而C为终点end柱子。
以上是作者对汉诺塔这一经典小游戏的全部思路和看法,若有错误或者不足之处,欢迎您在评论区下面留下你的宝贵意见!
如果这篇文章有帮助到你,请留下你的点赞收藏评论+关注,这将对我产生极大的动力!学海无涯,我与你共勉!