#include<malloc.h>
#include<limits.h>
#include<stdio.h>
#include<graphics.h>
#include<io.h>
#include<math.h>
#include<process.h>
#include<conio.h>
#include<dos.h>
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 1
#define STACK_INIT_SIZE 10 /* 存储空间初始分配量 */
#define STACKINCREMENT 2 /* 存储空间分配增量 */
#define N 8     /*棋盘大小*/
typedef  int Status;
typedef struct chess
{
   int x;
   int y;
   int d;
}chess;

typedef chess SElemType; 
int dir[N][N][8]; /*按各点权值递升存放待走方向,每点8个*/
int weight[N][N]; /*各点的权值*/
int board[N][N];
int step[N][N];

int HTry1[8]={-2,-1,1,2,2,1,-1,-2};
int HTry2[8]={1,2,2,1,-1,-2,-2,-1};
char ch;
int h,i,j,k,l,st,x,y;



/*栈的顺序存储表示 */
typedef struct SqStack
{
   SElemType *base; /* 在栈构造之前和销毁之后,base的值为NULL */
   SElemType *top; /* 栈顶指针 */
   int stacksize; /* 当前已分配的存储空间,以元素为单位 */
}SqStack; /* 顺序栈 */
 Status InitStack(SqStack *S)
 { /* 构造一个空栈S */
   (*S).base=(SElemType *)malloc(STACK_INIT_SIZE*sizeof(SElemType));
   if(!(*S).base)
     exit(OVERFLOW); /* 存储分配失败 */
   (*S).top=(*S).base;
   (*S).stacksize=STACK_INIT_SIZE;
   return OK;
 }
 Status StackEmpty(SqStack S)
 { /* 若栈S为空栈,则返回TRUE,否则返回FALSE */
   if(S.top==S.base)
     return TRUE;
   else
     return FALSE;
 }
Status GetTop(SqStack S,SElemType *e)
 { /* 若栈不空,则用e返回S的栈顶元素,并返回OK;否则返回ERROR */
   if(S.top>S.base)
   {
     *e=*(S.top-1);
     return OK;
   }
   else
     return ERROR;
 }
Status SetTop(SqStack S,SElemType *e)
{
   if(S.top>S.base)
   {
     *(S.top-1)=*e;
     return OK;
   }
   else
     return ERROR;
}
 Status Push(SqStack *S,SElemType e)
 { /* 插入元素e为新的栈顶元素 */
   if((*S).top-(*S).base>=(*S).stacksize) /* 栈满,追加存储空间 */
   {
     (*S).base=(SElemType *)realloc((*S).base,((*S).stacksize+STACKINCREMENT)*sizeof(SElemType));
     if(!(*S).base)
       exit(OVERFLOW); /* 存储分配失败 */
     (*S).top=(*S).base+(*S).stacksize;
     (*S).stacksize+=STACKINCREMENT;
   }
   *((*S).top)++=e;
   return OK;
 }

 Status Pop(SqStack *S,SElemType *e)
 { /* 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR */
   if((*S).top==(*S).base)
     return ERROR;
   *e=*--(*S).top;
   return OK;
 }



   /* --------------------------输出行走路线--------------------- */
void output(SqStack S)
{SElemType e;
 for(k=1;k<=2*N*N;k++)
 {Pop(&S,&e);
  i=e.x;j=e.y;
  step[i][j]=N*N+1-k;
  printf("the answer is:\n");
  for(i=0;i<N;i++)
  {
   for(j=0;j<N;j++)
   {printf("%d ",step[i][j]);}
   printf("\n");
   }
  }
}
/*计算各点的权值,可走的方向越多,权值越小------------------*/
void count()
{
 for(i=0;i<N;i++)
   for(j=0;j<N;j++)
      weight[i][j]=0;
       for(k=0;k<N;k++)
    {
     int x,y;
     x=i+HTry1[k];
     y=j+HTry2[k];
     if(x>=1&&x<=N&&y>=1&&y<=N)
      weight[i][j]++;
    }
}


int  check(int i,int j) /*检查(i,j)是否在棋盘内*/
{
if(i<1||i>8||j<1||j>8)
    return 0;
return 1;
}
/*--------------求出各点的最佳方向序列,即优先向权值小的方向
将各点的8个方向按该方向下的目标点的权值递增排列,
不可到达的目标点的方向放在最后面*/
void sort()
{
int m,n1,n2,x1,y1,x2,y2,d1,d2;
for(i=0;i<N;i++)
 for(j=0;j<N;j++)
  {
   for(k=0;k<8;k++)
   dir[i][j][k]=k;
   for(k=0;k<8;k++)
   {
   for(m=k+1;m<8;m++) /*对每个方向考察看有没有更好的*/
    {
     d1=dir[i][j][k];
     x1=i+HTry1[d1];
     y1=j+HTry2[d1];
     d2=dir[i][j][m];
     x2=i+HTry1[d2];
     y2=j+HTry2[d2];
     n1=check(x1+1,y1+1);
     n2=check(x2+1,y2+1);
     if((n1==0&&n2)||(n1&&n2&&weight[x1][y1]>weight[x2][y2]))
     /*k方向不可达到,而m方向可达到,或都可达到但m方向权值小*/
     {
     dir[i][j][k]=d2;
     dir[i][j][m]=d1;      /*交换两个方向值*/
     }
    }
   }
  }
}
/*输入函数*/
int scan(int i,int j)
{printf("Please input X :");
 scanf("%c",&i);
 printf("Please input Y :");
 scanf("\n%c",&j);
 if(i<'0'||i>'7'||j<'0'||j>'7')
 {printf("Input error!\nPlease input again\n");
  scan(i,j);}
 getch();
}




void main()
{
 SqStack a; /*存放路径*/
 SqStack b; /*存放方向*/
 SElemType c;
 SElemType d;/*中间变量*/
 SElemType f;  /*方向值,x值有效,y值恒为0*/
 SElemType m; /*当前点*/
 SElemType n; /*下一点*/
 InitStack(&a);
 InitStack(&b);

 printf("Please input X :");
 scanf("%c",&x);
 printf("Please input Y :");
 scanf("\n%c",&y);

 st=0;
 m.x =x; m.y =y; m.d=0;
 board[x][y]=1; /*第一点,在棋盘上标记1,表示已走*/
 InitStack(&a); /*建立空栈*/
 Push(&a,m); /*起始点的坐标和首选方向入栈*/
 while(1)
 {
  if (st==(N*N-1))/*若已走63步,棋盘上所有格都走完了*/
  { output(a); /*输出路径*/
    if(ch=='q') /*q退出*/
    break;
    else /*回退前一步*/
     { Pop(&a,&m);;/*退栈;*/
       Pop(&a,&m);
       k=m.d;
       m.d=k+1;
       Push(&a,m);
       st--;
       continue;
     }
  }
  if(StackEmpty(a)) break;
 GetTop(a,&m);

 if(m.d>=8)/*该点所有方向已走完,退栈*/
 {x=m.x;y=m.y;
 board[x][y]=0;/*抹去痕迹*/
 st--;
 Pop(&a,&m);/*退栈*/
 Pop(&a,&m);
 m.d=m.d+1;
 Push(&a,m);/*更改方向*/
 continue;
 }
 if(m.d<8)/*方向未走完*/
 {x=m.x;y=m.y;
  k=m.d;
  h=dir[x][y][k];
  n.x=x+HTry1[h];
  n.y=y+HTry2[h];
  if(check(n.x,n.y)&&board[n.x][n.y]==0)
   /*目标点在棋盘内且未被走过,则将目标点入栈同时标记当前点为已走过*/
  {x=n.x;y=n.y;
   board[x][y]=1;
   st++;     /*记录序号*/
   n.d=0;
   Push(&a,n);   /*存入目标点*/
  continue;
  }
  else/*目标点已被走过或目标点不在棋盘内,换方向*/
  {
   k=m.d;
   Pop(&a,&m);
   m.d=k+1;/*取下一个方向*/
   Push(&a,m);
   continue;/*继续 */
   }
 }
}
 getch();
 getch();
}