您的位置:首页 > 编程语言 > C语言/C++

C语言递归实现N宫格(九宫格)源码

2012-12-14 13:46 661 查看
     刚开始做九宫格的时候,能想到的就是几个for循环,很清楚很简单,同样也比较的低级,了解递归的魅力后,在高人的指点下,原来也可以这样的实现,写到这时,让我想到了当年教我们的老师,thanx,好代码,我还留着呢,我把当年写的源码分享一下,欢迎拍砖


     如果有更好的方法,也可交流一下。。。。。。。

/**************************************************************************************************************

 **文件:mian.c

 **编写者:huangminqiang

 **编写日期:2011年3月12号

 **简要描述:递归实现N宫格(九宫格)

 **修改者:

 **修改日期:

 **注:N>5后,运行结果需要的时间很长,适用于4-9-16宫格。

 **************************************************************************************************************/

#include <stdio.h>

#define N   4  //每行或列的数的个数

#define MAX   (N*N) //最大数

#define ROW_END  1  //行结束标志

#define COL_END  2  //列结束标志

#define LEFT_DOWN 3  //左下角标志

#define RIGHT_DOWN 4  //右下角标志

#define OTHER  0  //其它情况标志

//定义N宫格结构体

struct _ngg

{

 int num[MAX];  //定义填数的数组

 int val;   //判断相等的值

 int count;   //符合条件的组合数

};

//函数原型声明

//初始化结构体变量

void init(struct _ngg *pngg);

//开始填数

void fill(struct _ngg * pngg,int pos);

//获取标志

int getFlag(int pos);

//判断某个数在之前是否已填过,已填过则返回 1 ,否则返回 0

int isFilled(struct _ngg * pngg,int pos,int i);

//计算行和

int sumRow(struct _ngg * pngg,int pos);

//计算列和

int sumCol(struct _ngg * pngg, int pos);

//计算左上-右下对角和

int sumLU_RD(struct _ngg * pngg);

//计算右上-左下对角和

int sumRU_LD(struct _ngg * pngg);

//打印数组

void prt(struct _ngg * pngg);

 

//主函数,初始化并开始按位置填数

int main(void)

{

 //变量声明

 struct _ngg ngg = {0};

 //初始化结构体变量

 init(&ngg);

 printf("N = %d, MAX = %d, val = %d\n",N,MAX,ngg.val);

 //开始填数

 fill(&ngg,0);

 return 0;

}

//初始化结构体变量

void init(struct _ngg *pngg)

{

 //计算val的值

 pngg->val = MAX * (MAX + 1) / 2 / N;

}

//子函数实现填数

void fill(struct _ngg * pngg,int pos)

{

 //声明变量

 int flag = getFlag(pos);  //结束标志

 int i;

 //从 1 到 MAX 逐个填入数组的 pos  位置

 for(i = 1; i <=MAX; i++)

 {

  //判断 i 在前面有没有填过,填过则填下一个数

  if(isFilled(pngg,pos,i))

  {

   continue;

  }

  //填入 i 到 pos 位置

  pngg->num[pos] = i;

  //根据 flag 分情况进行处理

  switch(flag)

  {

  //行结束

  case ROW_END:

   //如果行和相等则继续填下一个位置

   if(pngg->val == sumRow(pngg,pos))

   {

    fill(pngg,pos+1);

   }

   break;

  //列结束

  case COL_END:

   //如果列和相等则继续填下一个位置

   if(pngg->val == sumCol(pngg,pos))

   {

    fill(pngg,pos+1);

   }

   break;

  //左下角

  case LEFT_DOWN:

   //如果列和、右上-左下对角和相等则填下一个位置

   if(pngg->val == sumCol(pngg,pos) &&

    pngg->val == sumRU_LD(pngg))

   {

    fill(pngg,pos+1);

   }

   break;

  //右下角

  case RIGHT_DOWN:

   //如果行和、列和、左上-右下对角和相等则打印数组

   if(pngg->val == sumRow(pngg,pos) &&

    pngg->val == sumCol(pngg,pos) &&

    pngg->val == sumLU_RD(pngg) )

   {

    prt(pngg);

   }

   break;

  //其它情况

  //case OTHER:

  default:

   //其它情况填下一个位置

   fill(pngg,pos+1);

  }

 }

}

//获取标志

int getFlag(int pos)

{

 //如果到了行尾,但不是最后一个元素则为行结束

 if(0 == (pos + 1) % N && MAX - 1 != pos)

 {

  return ROW_END;

 }

 //如果到了列尾,但不是第 0 列,也不是最后一个元素,则为列结束

 if(pos > N * (N - 1) && MAX - 1 != pos)

 {

  return COL_END;

 }

 //如果是最后一行,并且是第 0 列,则为左下角

 if(pos == N * (N - 1))

 {

  return LEFT_DOWN;

 }

 //如果是最后一个元素,则是右下角

 if(MAX - 1 == pos)

 {

  return RIGHT_DOWN;

 }

 //除此之外是其它情况

 return OTHER;

}

//判断某个数在之前是否已填过,已填过则返回 1 ,否则返回 0

int isFilled(struct _ngg * pngg,int pos,int i)

{

 int j;

 for(j = 0; j < pos;j++)

 {

  if(pngg->num[j] == i)

  {

   return 1;

  }

 }

 return 0;

}

//计算行和

int sumRow(struct _ngg * pngg,int pos)

{

 int i,sum = 0;

 //从第 pos 个元素往回加

 for(i = pos; i > pos - N; i--)

 {

  sum += pngg->num[i];

 }

 return sum;

}

//计算列和

int sumCol(struct _ngg * pngg, int pos)

{

 int i,sum = 0;

 //从第 pos 个元素往上加

 for(i = pos; i >= 0; i -= N)

 {

  sum += pngg->num[i];

 }

 return sum;

}

//计算右上-左下对角和

int sumRU_LD(struct _ngg * pngg)

{

 int i,sum = 0;

 //从第 N - 1 个元素开始每次跳过 N - 1 个元素累加

 for(i = N - 1; i < MAX -1; i += N - 1)

 {

  sum += pngg->num[i];

 }

 return sum;

}

//计算左上-右下对角和

int sumLU_RD(struct _ngg * pngg)

{

 int i,sum = 0;

 //从第 0 个元素开始每次跳过 N + 1个元素累加

 for(i = 0; i < MAX; i += N + 1)

 {

  sum += pngg->num[i];

 }

 return sum;

}

//打印数组

void prt(struct _ngg * pngg)

{

 int i;

 printf("-----------------------------------------%d\n",++pngg->count);

 for(i = 0; i < MAX; i++)

 {

  printf("\t%d",pngg->num[i]);

  if(0 == (i + 1) % N)

  {

   printf("\n");

  }

 }

}

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息