#include
#include
#define N 1000
void gotoxy(int x, int y); // 声明gotoxy函数
void colorxy(int x, int y); //声明colorxy函数
void hanoi(int n,char a,char b,char c); //声明hanoi函数
void move(int n,char a,char b); //声明move函数
void Print(); //声明print函数
void Printpan(int n); //声明Printpan函数
int a1=0,a2=0,a3=0;
int main()
{
int n=3;
char a='A',b='B',c='C';
colorxy(0x0b,0x0b);
printf("Please input n(0~9):");
scanf("%d",&n);
a1=n;
Print();
gotoxy(0,11-n);
Printpan(n);
Sleep(500);
gotoxy(0,12);
hanoi(n,a,b,c);// 把n个盘借助C,A-->B
return 0;
}
void gotoxy(int x, int y) //定义gotoxy函数(功能:将光标移动到指定位置说明:gotoxy(x,y)将光标移动到指定行y和列x。设置光标到文本屏幕的指定位置,其中参数x,y为文本屏幕的坐标。)
{
COORD coord = {x, y};
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
}
void colorxy(int x, int y) //定义colorxy函数
{
HANDLE hOut;
hOut = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(hOut, x|y);
}
void hanoi(int n,char a,char b,char c) //定义hanoi函数
{
if(n==1)
move(n,a,b);//把盘n,A-->B
else
{
hanoi(n-1,a,c,b);//把盘n上的n-1个盘借助B,A-->C
move(n,a,b);//把盘n,A-->B
hanoi(n-1,c,b,a);//把n-1个盘借助A,C-->B
}
}
void move(int n,char a,char b) //定义move函数
{
int static count=1;
int j;
switch(a)
{
case 'A':a1--;gotoxy(21+n,10-a1);
for(j=0;j<n*2;j++)printf(" \b\b");//删掉将要移走的盘
gotoxy(22,10-a1);colorxy(0x0a,0x0c);printf("|");//把删掉的|加上
break;
case 'B':a2--;gotoxy(38+n,10-a2);
for(j=0;j<n*2;j++)printf(" \b\b");//删掉将要移走的盘
gotoxy(39,10-a2);colorxy(0x0a,0x0c);printf("|");//把删掉的|加上
break;
case 'C':a3--;gotoxy(55+n,10-a3);
for(j=0;j<n*2;j++)printf(" \b\b");//删掉将要移走的盘
gotoxy(56,10-a3);colorxy(0x0a,0x0c);printf("|");//把删掉的|加上
break;
}
gotoxy(15,13);
printf("%3d. move %d, %c-->%c\n",count++,n,a,b);
switch(b)
{
case 'A':gotoxy(23-n,10-a1);a1++;
colorxy(0x0a,0x0a);
for(j=0;j<n*2-1;j++)
printf("=");gotoxy(0,22);Sleep(N);
break;
case 'B':gotoxy(40-n,10-a2);a2++;
colorxy(0x0a,0x0a);
for(j=0;j<n*2-1;j++)
printf("=");gotoxy(0,22);Sleep(N);
break;
case 'C':gotoxy(57-n,10-a3);a3++;
colorxy(0x0a,0x0a);
for(j=0;j<n*2-1;j++)
printf("=");gotoxy(0,22);Sleep(N);
break;
//colorxy(0x06,0x06);
}
}
void Print() //定义Print函数
{
printf("\n\n");
colorxy(0x0a,0x0c);
printf("\t\t | | | \n");
printf("\t\t | | | \n");
printf("\t\t | | | \n");
printf("\t\t | | | \n");
printf("\t\t | | | \n");
printf("\t\t | | | \n");
printf("\t\t | | | \n");
printf("\t\t | | | \n");
printf("\t\t -----A----- -----B----- -----C-----\n");
colorxy(0x0c,0x0c);gotoxy(22,11);printf("A");
gotoxy(39,11);printf("B");
gotoxy(56,11);printf("C");
colorxy(0x0a,0x0a);
}
void Printpan(int n) //定义Printpan函数
{
int i,j;
for(i=1;i<=n;i++)
{
for(j=1;j<=23-i;j++)
printf(" ");
for(j=1;j<=i*2-1;j++)
printf("=");
printf("\n");
}
}
请帮忙每句都注释一下,我是初学者,这个程序里的colorxy和gotoxy和Printpan和move都看不怎么懂
汉诺塔是一个递归的问题,不过这个递归没有求阶乘的递归过程那么明显。你应该将左中右一条直线排列上的三个杆在逻辑上放到一个等边三角形的三个顶点上,然后弄清楚你要移动第N个块时必须通过剩余的一个杆(辅助杆)来移动到另一个杆(目标杆)上,这样三个杆现在应该叫位置杆(放置第N个块的杆)、辅助杆和目标杆,也就是每次递归都是把位置杆上的块通过辅助杆移动到目标杆上,递归就在于这个逻辑,而不是它们具体的物理位置,这样你就能知道递归函数三个参数具体每次应该用哪个杆而不糊涂,弄清本质比看人家代码更重要,希望有所帮助。
如此代码不值得学习了,给你个更值得学习的吧:{CSDN:CODE:357585}
CSDN移动问答
/**
* 河内塔问题求解(递归:中序遍历二叉树)
*
* @param level 缩进级别:用于控制输出的“缩进”量,纯美观设计,初学者可忽略它;
* 递归树的根缩进量为0,每下一层,则缩进量加8,在标准输出上可以得到比较美观的效果;
* @param n 要移动的盘子个数
* @param i 递归层级;递归树的叶子节点层级为1,越往上层,层级越高;
* @param a 源柱子,定义域为{'a','b','c'}
* @param b 中间柱子,定义域为{'a','b','c'}
* @param c 目标柱子,定义域为{'a','b','c'}
*
* @inv 缩进级别与递归层级的和恒为递归树根节点对应的n值;
* @inv {a,b,c}=={'a','b','c'}
*/
void hanoi_move(int level, int n, int *i, char a, char b, char c)
{
if(n==1)
{
// 只有一个盘子:直接搬到目标柱子上
printf("%4d,%*d:%c->%c\n",++i[0],level*8,n,a,c);
}
else
{
// 先把源柱子上的n-1个盘子搬到中间柱子上
hanoi_move(level+1,n-1,i,a,c,b);
// 再把源柱子上的第n个盘子搬到目标柱子上
printf("%4d,%*d:%c->%c\n",++i[0],level*8,n,a,c);
// 最后把中间柱子上的n-1个盘子搬到目标柱子上
hanoi_move(level+1,n-1,i,b,a,c);
}
}
调用:
#include <stdlib.h>
#include <stdio.h>
//void hanoi_move(...)...
int main(int argc, const char *argv[])
{
int some_i=0;
int n = 7;
if (1<argc)
{
n = atol(argv[1]);
}
hanoi_move(0, n, &some_i, 'a', 'b', 'c');
return 0;
}