dos下实现汉若塔动画的移动程序和思想

来源:互联网 发布:知乎数据挖掘考研 编辑:程序博客网 时间:2024/06/05 04:59

程序的主要思想是标识盘子的位置,和该入的柱子号,很容易让人联想到栈实现,设立三个栈,动态记录盘子数和要出栈的序号

 

定义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 希望能够结识更多编程的好友。。。。。。~~~~~~~~~~~~~~~~~~··