您的位置:首页 > 其它

关于手机数字类游戏的探索(一)

2009-12-31 09:42 267 查看
2009-12-31

关于手机数字类游戏的探索(一)

如果看动态分配不爽就看续(另续中代码经过小点优化)。

/*关于手机数字类游戏的探索(一)。
*行列皆递增数组矩阵
*说明:
*对于给定的行列方阵
*矩阵应满足:每一行递增,每一列递增。
*数据最小为1,最大为个数。
求出所有满足条件的排列组合并输出。
*例:1--> 2	     1--> 3
*    |	  |	     |	  |
*    V    V          V    V
*    3--> 4      及  2--> 4    是2行2列的行列递增方阵
*  箭头(下箭头不知道怎么表示就用V了)所示为递增方向
*/
#include <stdio.h>
#include <malloc.h>//用动态分配内存
#include <string.h>//用memset(,,);
#include <conio.h>//getch();
#include <windows.h>//OutputDebugString();
#include <assert.h>

/*求解*/
bool SearchSolutionSet(int n, int m);//n 是方阵行数,m方阵列数

/*从位置posx,posy开始往后求解*/
bool SearchFromPos(int * ptrArr,//指针:存储方阵数据
int posx, //在列方向上的计数
int posy,//在行方向上的计数
int *flagused//数字使用状态
);

/*从位置posx,posy开始往后清除数据(含此点),清除含义:赋值为边界值*/
bool CleanLaterPart(int *ptrArr,
int row,//有效行数(不含边界)
int col,//有效列数(不含边界)
int posx,
int posy,
int *flagused);

/*判定当前数num能否放在posx,posy位置*/
bool IsPossible(int * ptrArr,
int posx,
int posy,
int num);

/*输出方阵*/
bool OutPut(int *ptrArr,
int row,
int col);

/*用于调试的函数*/
void OutPutDebug(int *flagused);//用于Debug,输出数字使用状态
/*------------------------------------------------------------------------------------*/
int min=0;			//边界小值
int max=0;			//边界大值
int row=0;			//行,y坐标
int col=0;			//列,x坐标
int count=0;		//记录解个数
int len=0;		//有用的数组长度(不含边界)
int num=0;		//Debug用,查看递归次数
/*------------------------------------------------------------------------------------*/
/* IN:行,列数
* OUT:true 有解,false 无解*/
/*求解*/
bool SearchSolutionSet(int n, int m)//n 是方阵行数,m方阵列数
{
assert(n>0&&m>0);

min=0;    //边界小值为0
max=n*m+1;//最大数为n*m,让边界大值为n*m+1
row=n;
col=m;
count=0;		//记录解个数
len=row*col;		//有效长度

int * ptrArr=(int *)malloc((row+2)*(col+2)*sizeof(int));//申请空间存储方阵,带边界
int * flagused=(int *)malloc((len+1)*sizeof(int));//flag[i]=ture;数i被使用//flag[i]=flase;数i未被使用

for(int i=0;i<row+2;i++)
for(int j=0;j<col+2;j++)
if(i==0||j==0)//初始化,只有当i=0的行,j=0列是最小值边界
*(ptrArr+i*(col+2)+j)=min;
else    *(ptrArr+i*(col+2)+j)=max;//其它为MAX
memset(flagused,0,(len+1)*sizeof(int));//初始标记0,全部可用

bool isSoluable=false;		//有无解标记;false : 无 ,ture :有

isSoluable=SearchFromPos(ptrArr, 1, 1, flagused);

free(flagused);
flagused=NULL;
free(ptrArr);
ptrArr=NULL;

return isSoluable;
}
/*从位置posx,posy开始往后求解*/
bool SearchFromPos(int * ptrArr,//指针:存储方阵数据
int posx, //在列方向上的计数
int posy,//在行方向上的计数
int *flagused//数字使用状态
)
{
assert(ptrArr!=NULL);

++num;
/*	OutPut(ptrArr,row,col);
printf("/n第%d次调用.",num);//调试用
OutPutDebug(flagused);
*/
int * useable=(int *)malloc(len*sizeof(int));//记录当前所有可用数
memset(useable,0,len*sizeof(int));

bool flagsoluable=false;
int cnuseable=0;
int nextposx=0;
int nextposy=0;
int curnum=0;
if(posx==1&&posy==1)//入口点
{
*(ptrArr+1*(col+2)+1)=1;
*(flagused+1)=1;
*(ptrArr+row*(col+2)+col)=len;
*(flagused+len)=1;
flagsoluable=SearchFromPos(ptrArr, 2, 1, flagused);

printf("/n返回,总次数%d./n",num);
free(useable);
useable=NULL;
return flagsoluable;//出口点,返回有无解
}
for(int i=2;i<len;i++)//查找标记,记录可用数目,并放入可用数组
if(*(flagused+i)==0)
{
*(useable+cnuseable)=i;
cnuseable++;
}

//	printf("有%d个可用数:/n",cnuseable);//调试用

if(cnuseable==0)//到达最后一个点,一定是解
{
count++;
printf("/n第%d个解:/n",count);
OutPut(ptrArr, row, col);//输出方阵

printf("/n当前调用%d次有解返回.",num);
free(useable);
useable=NULL;
return true;//有解:返回上一层继续搜索
}
if(posx<0||posx>col||posy<0||posy>row)//这个条件会发生,但在前面cnuseable一定是0
return 0;			//程序到不了这就会返回
for(i=0;i<cnuseable;i++)//进行可用数遍历
{
curnum=*(useable+i);
//if(*(flagused+curnum)) continue;//不出意外,这个条件为假
if(IsPossible(ptrArr, posx, posy, curnum))//数curnum可以放
{
*(ptrArr+posy*(col+2)+posx)=curnum;//放入当前数
*(flagused+curnum)=1;//更新标记
if((posx+1)%(col+1))//没到下一行
{
nextposx= posx+1;//下一位置的计算,对应于一维的映射
nextposy= posy;
}
else				//到了下一行
{
nextposx= 1;
nextposy= (posy+1)%(row+1);
}
if(!flagsoluable)//只要有一个解就返回true;
flagsoluable=SearchFromPos(ptrArr, nextposx, nextposy, flagused);//放下一位置
else SearchFromPos(ptrArr, nextposx, nextposy, flagused);
//返回点;
*(ptrArr+posy*(col+2)+posx)=max;
*(flagused+curnum)=0;//当前路径当前数已做解处理,释放标记
}
//数curnum不能放,i++,进行下个可用数的判定。
}
//	前面已做清除
//	CleanLaterPart(ptrArr, row, col, posx, posy, flagused);//清除数组中在当前位置(含)之后的数据,以防下次赋值判定时有误
free(useable);
useable=NULL;
return flagsoluable;//返回可行状态
}
/*------------------------------------------------------------------------------------*/
void OutPutDebug(int *flagused)//输出数字使用情况
{
printf("/n当前数字使用情况:");

for(int i=1;i<len+1;i++)
{
printf("%3d=%3d  ",i,*(flagused+i));//第i个标记=0:i可用;第i个标记=1:i不可用/已使用(如:第0个,第1个)
}
printf("/n");

}
/*------------------------------------------------------------------------------------*/
/*输出方阵*/
bool OutPut(int *ptrArr,
int row,
int col)
{
printf("/n");
for(int i=1;i<=row;i++)
{
if(i!=1)
{
for(int j=1;j<=col;j++)
{
printf("%-5.1s","|");
}
printf("/n");
}
for(int j=1;j<=col;j++)
{
if(*(ptrArr+i*(col+2)+j)<max)
{
printf("%-3d",*(ptrArr+i*(col+2)+j));
}
else {
printf("MAX");
}
if(j!=col)
{
printf("->");
}
}
printf("/n");
}
char ch;
if(count&&count%10==0)
{
printf("/n当前是否先等待:(Y/N)/n要退出等待继续请输入:N/n");
ch=getch();
if(ch=='Y'||ch=='y')
{
ch=getch();
while(ch!='N'||ch!='n')
ch=getch();
}
}
return true;
}
/*------------------------------------------------------------------------------------*/

/*判定当前数num能否放在posx,posy位置*/
bool IsPossible(int * ptrArr,
int posx,
int posy,
int num)
{
if(num>=*(ptrArr+posy*(col+2)+(posx+1))||        	 //比右大
num<=*(ptrArr+posy*(col+2)+(posx-1))||	//比左小
num>=*(ptrArr+(posy+1)*(col+2)+posx)||	//比下大
num<=*(ptrArr+(posy-1)*(col+2)+posx))	//比上小
return false;
else return true;
}

/*从位置posx,posy开始往后清除数据(含此点);清除含义:赋值为边界值*/
bool CleanLaterPart(int *ptrArr,
int row,//有效行数(不含边界)
int col,//有效列数(不含边界)
int posx,
int posy,
int *flagused)
{
printf("/nclean later part of the array!");

while(posy!=row||posx!=col)
{
*(ptrArr+posy*(col+2)+posx)=max;
*(flagused+*(ptrArr+posy*(col+2)+posx))=0;
if((posx+1)%(col+1))
{
posx++;
}
else{
posx=1;
posy++;
}
}
return true;
}
/*------------------------------------------------------------------------------------*/

int main()
{
int n=3,m=3;
/*	printf("请输入数组大小n=行,m=列!/n");
printf("n=");
scanf("%d",&n);
printf("/nm=");
scanf("%d",&m);
printf("/n");
*/
SearchSolutionSet(n,m);
return 0;
}
/*------------------------------------------------------------------------------------*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: