1.问题
汉诺塔(Hanoi Tower),又称河内塔,源于印度一个古老传说。
大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。
大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。
并且规定,任何时候,在小圆盘上都不能放大圆盘,且在三根柱子之间一次只能移动一个圆盘。
问:应该如何操作?
2.推导过程(包含代码)
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
void Hanoi(int n, char arr1[], char arr2[], char arr3[]);//函数声明,这是后面函数写完后补的
void Print(char arr[]);
int main()
{
int i = 0;
char arr1[5] = { 0 };//为了方便观察我将64个盘子改为4个盘子,其实就是改了几个数据,操作思路一致
char arr2[5] = { 0 };
char arr3[5] = { 0 };//使用三个数组代表三个柱子,这个[]里的5表示这个数组包含5个数据,
//实际上是从arr[0]到arr[4],要注意定义数组和使用数组时的差异
for (i = 1; i <= 4; i++)
{
arr1[i] = i;//对第一个柱子进行初始化定义
}
Hanoi(4, arr1, arr2, arr3);//对三个柱子上的盘子进行操作
return 0;
}
//推理的一部分
//void Hanoi(char arr1[], char arr2[], char arr3[])
//{
// Move(arr1[1], arr2[1]);//第一个柱子上最上面的盘子(arr1[1],也就是1)与第二个柱子相同的位置交换
// Move(arr1[2], arr3[2]);
// Move(arr2[1], arr3[1]);//至此我们已经完成了2个盘子从第一个柱子到其他柱子的交换
//
// //注意:下面的arr[3]到arr[4]我们可以让它空着,
// //因为arr[1]与arr[2]的两个空间完全够2个盘子在不同柱子之间的交换了,
// //1个盘子与多个盘子之间的交换同理,这样方便代码的表达
//
// //要完成3个盘子,只需将arr1[3]与arr2[3]交换,
// //然后重复2个盘子的交换,将第三个柱子上的2个盘子转移到第二个柱子上
//
// //要完成4个盘子,只需将arr1[4]与arr3[4]交换,
// //然后重复3个盘子的交换,将第二个柱子上的3个盘子转移到第三个柱子上
//
// //由此找到规律与具体解法,接下来是将想法具体为代码
//}
//这里我是用的是递归的方法,我认为使用递归要从结尾与起点思考,即正推与倒退
void Hanoi(int n, char arr1[], char arr2[], char arr3[])
//这个函数意味着将arr1[]上n个"盘子"移到arr2[]上,而arr3[]只起辅助作用
{
if (1 == n)
{
int a = arr1[1];//本来想写个函数的,学浅,写了运行不起来,学了指针再说
arr1[1] = arr2[1];
arr2[1] = a;
Print(arr1);
Print(arr2);
Print(arr3);
printf("\n");//对汉诺塔问题操作过程的观察,作者水平问题,三组数据需要自己排序
}
else
{
Hanoi(n - 1, arr1, arr3, arr2);//一柱子上n-1个盘子移到三柱子上
int b = arr1[n];
arr1[n] = arr2[n];
arr2[n] = b;//一柱子上最底下的盘子移到二柱子上
Print(arr1);
Print(arr2);
Print(arr3);
printf("\n");//对汉诺塔问题操作过程的观察,三组数据需要自己排序
Hanoi(n - 1, arr3, arr2, arr1);//三柱子上n-1个盘子移到二柱子上
}
}
void Print(char arr[])
{
int i = 0;
for (i = 1; i <= 4; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
}
3.代码(只想看代码来这里)
3.1作者自己写的
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
void Hanoi(int n, char arr1[], char arr2[], char arr3[]);
void Print(char arr[]);
int main()
{
int i = 0;
char arr1[5] = { 0 };
char arr2[5] = { 0 };
char arr3[5] = { 0 };
for (i = 1; i <= 4; i++)
{
arr1[i] = i;
}
Hanoi(4, arr1, arr2, arr3);
return 0;
}
void Hanoi(int n, char arr1[], char arr2[], char arr3[])
{
if (1 == n)
{
int a = arr1[1];
arr1[1] = arr2[1];
arr2[1] = a;
Print(arr1);
Print(arr2);
Print(arr3);
printf("\n");
}
else
{
Hanoi(n - 1, arr1, arr3, arr2);
int b = arr1[n];
arr1[n] = arr2[n];
arr2[n] = b;
Print(arr1);
Print(arr2);
Print(arr3);
printf("\n");
Hanoi(n - 1, arr3, arr2, arr1);
}
}
void Print(char arr[])
{
int i = 0;
for (i = 1; i <= 4; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
}
3.2优秀简洁代码推荐
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
void Move(int x, int y);
void Hanoi(int n, char arr1, char arr2, char arr3);
int main()
{
int n = 4;
Hanoi(n, 'A', 'B', 'C');
return 0;
}
void Hanoi(int n, char arr1, char arr2, char arr3)
{
if (n == 1)
{
Move(arr1, arr2);
}
else
{
Hanoi(n - 1, arr1, arr3, arr2);
Move(arr1, arr2);
Hanoi(n - 1, arr3, arr2, arr1);
}
}
void Move(int x, int y)
{
printf("%c -> %c\n", x, y);
}
4.总结
边写边想,先初始化数据(用不用的到另说)。
想出问题解决方法是一大难关,用代码表达出来也是。