目录
汉诺塔问题
1.汉诺塔问题的递归算法
2.图像模拟汉诺塔(easyx图像库)
注:编译器为 visual stdio 2022 较为严格 如
char a;
scanf_s("%c",&a,1);
scanf的写法发生变化 取地址后要表明数字,字符串的话写字符数组长度,单个字符写1.
1.汉诺塔问题的递归算法
#include<stdio.h>
void moveone(char, char);
void move(int, char, char, char);
int sum = 0;
int main(void)
{
char x, y, z;
scanf_s("%c %c %c", &x,1, &y,1, &z,1);
char ch;
ch = getchar();//过滤前导字符
int n;
scanf_s("%d", &n);
move(n, x, y, z);//开始移动
return 0;
}
void moveone(char v, char u)
{
sum++;
printf("%c->%c %d\n", v, u,sum);
}
void move(int n, char x, char y, char z)
{
if (n > 0)
{
move(n - 1, x, z, y);
moveone(x, y);
move(n-1,z, y, x);
}
}
最终会出现如下移动结果(以4次为例)输入 a b c 4 回车
a->c 1
a->b 2
c->b 3
a->c 4
b->a 5
b->c 6
a->c 7
a->b 8
c->b 9
c->a 10
b->a 11
c->b 12
a->c 13
a->b 14
c->b 15
这是简单的递归思想,按照以上步骤移动一定是正确的并且是移动次数最少的,那么这便为我们下面的图像化创造了条件。
2.图像模拟汉诺塔(easyx图像库)
说到图像化,c++图像库Easyx可以简单实现图形的显示功能,我们用这个图形库来编辑代码。
我们采用源文件头文件相结合的方式。
源文件如下:
#include<stdio.h>
#include<graphics.h> //图形库头文件
#include<stdlib.h>
#include"slx.h" //我们自己的头文件
char x, y, z; //三个柱子的名称
int top1 = -1; //栈1
bk stack1[100];
int n1;
int top2 = -1; //栈2
bk stack2[100];
int n2;
int top3 = -1; //栈3
bk stack3[100];
int n3;
bk blocks[100]; //汉诺塔块
int sum = 0; //计数器
int main(void)
{
scanf_s("%c %c %c", &x, 1, &y, 1, &z, 1);
char ch;
ch = getchar(); //过滤前导字符
int n;
scanf_s("%d", &n);
n1 = n; //n1 n2 n3为栈的容量
n2 = n;
n3 = n;
int i = 0; //为块赋值序号和半长
for (; i < n; i++)
{
blocks[i].xu = i + 1;
blocks[i].chang = 10*(i+1);
}
i = n-1;
for (; i >=0; i--) //从大到小压到栈1中
{
push1(blocks[i]);
}
initgraph(1000,1000); //窗口
xian(); //显示图像
system("pause");
move(n, x, y, z); //移动
system("pause"); //必要的指令 让窗口停留
closegraph();
return 0;
}
头文件如下:
#ifndef _SLX_H_
#define _SLX_H_
#include<stdio.h>
#include<graphics.h>
#include<stdlib.h>
typedef struct block
{
int xu;
int chang;
}bk; //在头文件中声明结构体
extern int top1; //以下为引用外部变量
extern bk stack1[100];
extern int n1;
extern int top2;
extern bk stack2[100];
extern int n2;
extern int top3;
extern bk stack3[100];
extern int n3;
extern int sum;
extern char x;
extern char y;
extern char z;
extern int n; //以下为进栈出栈函数
void push1(bk i)//进栈
{
if (top1 >= n1 - 1)//满栈
{
;
}
else
{
top1++;//不满栈 栈顶指针加一再进栈
stack1[top1] = i;
}
}
bk pop1(void)
{
if (top1 < 0)//空栈
{
;
}
else
{
bk i = stack1[top1];//栈不空 取值
top1--;//栈顶指针减一
return i;//弹出
}
}
void push2(bk i)//进栈
{
if (top2 >= n2 - 1)//满栈
{
;
}
else
{
top2++;//不满栈 栈顶指针加一再进栈
stack2[top2] = i;
}
}
bk pop2(void)
{
if (top2 < 0)//空栈
{
;
}
else
{
bk i = stack2[top2];//栈不空 取值
top2--;//栈顶指针减一
return i;//弹出
}
}
void push3(bk i)//进栈
{
if (top3 >= n3 - 1)//满栈
{
;
}
else
{
top3++;//不满栈 栈顶指针加一再进栈
stack3[top3] = i;
}
}
bk pop3(void)
{
if (top3 < 0)//空栈
{
;
}
else
{
bk i = stack3[top3];//栈不空 取值
top3--;//栈顶指针减一
return i;//弹出
}
}
/*图像显示函数*/
void xian(void)
{
setbkcolor(RGB(0, 199, 140));
cleardevice();
setlinecolor(RGB(138, 43, 226));
line(100, 900, 900, 900);
line(300, 100, 300, 900);
line(500, 100, 500, 900);
line(700, 100, 700, 900);
int i;
i = 0;
for (int o=10; i <=top1;i++,o+=20)
{
rectangle(300 - stack1[i].chang, 900 - (o + 10), 300 + stack1[i].chang, 900 - (o - 10));
}
i = 0;
for (int p = 10; i <=top2; i++, p += 20)
{
rectangle(500 - stack2[i].chang, 900 - (p + 10), 500 + stack2[i].chang, 900 - (p - 10));
}
i = 0;
for (int q = 10; i <=top3; i++, q += 20)
{
rectangle(700 - stack3[i].chang, 900 - (q + 10), 700 + stack3[i].chang, 900 - (q - 10));
}
}
/*移动函数*/
void moveone(char v, char u)
{
sum++;
printf("%c->%c %-10d", v, u, sum);
if (v == x && u == y)
{
push2(pop1());
}
if (v == x && u == z)
{
push3(pop1());
}
if (v == y && u == z)
{
push3(pop2());
}
if (v == y && u == x)
{
push1(pop2());
}
if (v == z && u == x)
{
push1(pop3());
}
if (v == z && u == y)
{
push2(pop3());
}
xian();
system("pause");
}
/*递归移动函数*/
void move(int n, char x, char y, char z)
{
if (n > 0)
{
move(n - 1, x, z, y);
moveone(x, y);
move(n - 1, z, y, x);
}
}
#endif
我们以8个为例 输入 a b c 8 回车
显示如下
继续按回车到结束
完结撒花
以上就是汉诺塔问题的图像化。
总结,汉诺塔的背后是较难理解的递归思想,我们可以借此来锻炼递归的思维,就是拆分问题,逐层解决,最终完成目标。
希望以上内容对你有所帮助,也祝你的生活轻松愉快。