程序的主要思想是标识盘子的位置,和该入的柱子号,很容易让人联想到栈实现,设立三个栈,动态记录盘子数和要出栈的序号
定义t11.h包含常用头文件
#include"stdio.h"
#include"string.h"
#include"ctype.h"
#include"malloc.h"
#include"stdlib.h" //atoi(),exit();
#include"io.h" //eof()
#include"math.h"
#include"windows.h"
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
typedef int Status;
typedef int Boolean;
int p=1; // 全局变量,记录移动步数
定义数据类型包含于头文件hrt.h中
#define INIT_STACK_SIZE 40
#define STACK_ADD 10
typedef struct
{
int xu; // 对应的盘子序数
int zbj; // 对应的纵坐标
}cun;
typedef struct // 把位子放入栈中 线性表操作
{
cun *top;
cun *bottom;
int stacksize;
} Sqstack;
定义实现函数包含于hrt.cpp中
extern p; // 引用全局变量
void initstack(Sqstack &L) // 初始化栈操作
{
L.bottom=(cun*)malloc(INIT_STACK_SIZE*sizeof(cun));
if(!L.bottom)
{
printf("内存分配失败!!");
exit(-1);
}
L.top=L.bottom;
L.stacksize=INIT_STACK_SIZE;
}
Status push(Sqstack &L,int xu,int zbj) // 压入位置 q表示行,p表示列
{
if(L.top-L.bottom >= L.stacksize)
{ L.bottom=(cun*)realloc(L.bottom,(L.stacksize+STACK_ADD)*sizeof(cun));
if(!L.bottom)
{
printf("内存分配失败!!");
exit(-1);
}
L.top=L.bottom+L.stacksize;
L.stacksize+=STACK_ADD;
}
L.top->xu=xu;
(L.top++)->zbj=zbj;
return OK;
}
Status pop(Sqstack &L,int &xu,int&zbj) // 弹出 将栈顶的元素带回
{
if(L.top == L.bottom)
return ERROR;
xu=(--L.top)->xu; // 这点自己犯的问题 不能--L.top->i 这样就表示值减1 没意义,出错
zbj=L.top->zbj;
return OK;
}
Status emptystack(Sqstack L) // 判断栈为空
{
if(L.top == L.bottom)
return OK;
else
return ERROR;
}
int gettop(Sqstack L,int &xu,int &zbj)
{
if(L.top == L.bottom)
return ERROR;
else
{
xu=(L.top-1)->xu;
zbj=(L.top-1)->zbj;
return OK;
}
}
void GotoConsoleXY(HANDLE hConsole,int x,int y) // 定位光标位置
{
COORD coordScreen={x,y};
SetConsoleCursorPosition(hConsole,coordScreen);
return;
}
void gotoxy(int x,int y) // 定位光标位置
{
HANDLE hStdOut=GetStdHandle(STD_OUTPUT_HANDLE);
GotoConsoleXY(hStdOut,x,y);
return;
}
void huatu(Sqstack &A,Sqstack &B,char (*b)[16],char (*a)[16],int e,int zbj,int l,int xu) // 画图
{
int xs,hs;
if(e<l) // 从左到右
{
for(int i=0;i<zbj-5;i++) // 从塔中出来到达顶端
{
gotoxy(e-xu+1,zbj-i); // 定位对应盘的起始盘子代号
printf("%s",*(b+xu-1)); // 输出对应的空格字符代号
gotoxy(e,zbj-i); // 定位盘子的位置
printf("|"); // 输出竖杠
gotoxy(e-xu+1,zbj-i-1); // 定位产生动画的下一个光标位置
printf("%s",*(a+xu-1)); // 打印出对应的盘子数
Sleep(50); // 暂停0.5毫秒
}
for(i=0;i<l-e;i++) // 平行移动
{
gotoxy(e-xu+1+i,5); // 定位平行的位置
printf("%s",*(b+xu-1)); // 将其对应的清除
gotoxy(e-xu+2+i,5); // 定位下一个单位
printf("%s",*(a+xu-1)); // 打印出对应的盘子
Sleep(20); // 暂停0.2毫秒
}
if(!emptystack(B)) //判断要移动到的盘子是否为空
gettop(B,xs,hs); // 得到该盘子的横行及序号
else
hs=14; // 将横行置为最底层
gotoxy(e-xu+1+i,5); // 将要入盘的第一个位置定位
printf("%s",*(b+xu-1)); // 输入对应空格覆盖
gotoxy(e-xu+1+i,6); // 定位入盘的光标位置
printf("%s",*(a+xu-1)); // 空格覆盖
Sleep(50); // 暂停0.5毫秒
for(int k=6;k<hs-1;k++) // 进入要移动的指定塔上
{
gotoxy(e-xu+1+i,k);
printf("%s",*(b+xu-1));
gotoxy(l,k);
printf("|");
gotoxy(e-xu+1+i,k+1);
printf("%s",*(a+xu-1));
Sleep(50);
}
push(B,xu,k); // 将序数和位置入栈
}
else // 从右到左
{
for(int i=0;i<zbj-5;i++)
{
gotoxy(e-xu+1,zbj-i);
printf("%s",*(b+xu-1));
gotoxy(e,zbj-i);
printf("|");
gotoxy(e-xu+1,zbj-i-1);
printf("%s",*(a+xu-1));
Sleep(50);
}
for(int k=e;k>=l;k--)
{
gotoxy(k-xu+1,5);
printf("%s",*(b+xu-1));
gotoxy(k-xu,5);
printf("%s",*(a+xu-1));
Sleep(20);
}
if(!emptystack(B))
gettop(B,xs,hs);
else
hs=14;
gotoxy(l-xu,5);
printf("%s",*(b+xu-1));
gotoxy(l-xu+1,6);
printf("%s",*(a+xu-1));
Sleep(50);
for( k=6;k<hs-1;k++)
{
gotoxy(l-xu+1,k);
printf("%s",*(b+xu-1));
gotoxy(l,k);
printf("|");
gotoxy(l-xu+1,k+1);
printf("%s",*(a+xu-1));
Sleep(50);
}
push(B,xu,k); // 将盘子序数和要入的光标位置
}
Sleep(500); // 暂停0.5秒
}
void move(Sqstack &A,Sqstack &B,Sqstack &C,char (*b)[16],char (*a)[16],char X,char Y)
{
int xu,zbj;
switch(X) // 匹配移动盘子代号
{
case 'A':
switch(Y)
{
case 'B':{
pop(A,xu,zbj); // 弹出对应盘子的序数和横行位置
huatu(A,B,b,a,16,zbj,40,xu);
p++; // 全局变量加1,表示移动了一步
};break;
case 'C':{
pop(A,xu,zbj);
huatu(A,C,b,a,16,zbj,64,xu);
p++;
};break;
};break;
case 'B':
switch(Y)
{
case 'A':{
pop(B,xu,zbj);
huatu(B,A,b,a,40,zbj,16,xu);
p++;
};break;
case 'C':{
pop(B,xu,zbj);
huatu(B,C,b,a,40,zbj,64,xu);
p++;
};break;
};break;
case 'C':
switch(Y)
{
case 'A':{
pop(C,xu,zbj);
huatu(C,A,b,a,64,zbj,16,xu);
p++;
};break;
case 'B':{
pop(C,xu,zbj);
huatu(C,B,b,a,64,zbj,40,xu);
p++;
};break;
}
}
}
void hrt(Sqstack &e,Sqstack &f,Sqstack &g,char (*b)[16],char (*a)[16],int n,char A,char B,char C)
{
if(n == 1)
{
gotoxy(28,3);
printf("(第%d步,第%d个盘): %c->%c ",p,1,A,C); // 动态显示移动盘子和步数
move(e,f,g,b,a,A,C);
}
else
{
hrt(e,f,g,b,a,n-1,A,C,B); // 递归调用
gotoxy(28,3);
printf(" ");
gotoxy(28,3);
printf("(第%d步,第%d个盘): %c->%c ",p,n,A,C);
move(e,f,g,b,a,A,C);
hrt(e,f,g,b,a,n-1,B,A,C);
}
}
最后就是在主函数里面进行调用了,定义文件main_hrt.cpp
#include"t11.h"
#include"hrt.h"
#include"hrt.cpp"
extern p; // 引用全局变量
void main()
{
int n;
Sqstack A,B,C;
initstack(A);
initstack(B);
initstack(C);
char a[][16]={"-","---","-----","-------","---------","-----------","-------------","---------------"}; // 定义盘子
char b[][16]={" "," "," "," "," "," "," "," "}; // 定义要覆盖对应的空格
printf("输入盘子数(<=8):");
scanf("%d",&n);
printf("\n\n\n\n\n");
if(n>8)
{
printf("输入不正确!");
exit(1);
}
for(int i=1;i<=8;i++)
printf("\t\t|\t\t\t|\t\t\t|\n");
printf("\t\t A\t\t\t B\t\t\t C\n");
for( i=0;i<n;i++) // 将盘子的代号入栈
{
gotoxy(17-n+i,13-i);
printf("%s",a[n-1-i]);
push(A,n-i,13-i);
}
printf("\n\n\n\n\n\n\n\n\n\n\n\n");
getchar(); getchar();
hrt(A,B,C,b,a,n,'A','B','C');
printf("\n\n\n\n\n\n\n\n\n\t\t\t移动结束!~~~~~@@@@~~~~~\n\t\t\t历经步数:%d 步\n",p-1);
getchar();
}
总结:程序的思路清晰就很好编写代码,只要基础功好,肯思考,就会一点一点进步,这是自己随手编写的一个小程序,全部完成花了将近4个多小时,但还是觉得自己的逻辑能力还行,编程的过程中也是一个渐渐熟悉的过程,我只用一个简单的栈操作完成了,想必以后我一定会用更好的方法编写完的。~~~~~~~~~~~~留住最真的于2012.04.04.21:49写。。。。。。
程序图片为: 希望大家批评指正,有更好的方法,欢迎交流分享。
代码的下载地址贴上:http://download.csdn.net/detail/wu10045125/4679585 希望能够结识更多编程的好友。。。。。。~~~~~~~~~~~~~~~~~~··