九宫格(安卓手机的图形锁有几种解锁图案)

这是一个计算九宫格图形锁所有可能解锁图案的C语言程序。程序通过递归方式,判断每个节点放置的位置是否合法,计算出所有可能的连接方法,并提供了是否打印每种情况的选项。
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<conio.h>


															//		______		//
                                                            //				    //
															//	 定义全局变量	//
															//					//
															//		~~~~~~		//

//记忆哪个位置放了结点的数组
int record[3][3]={0};

//计数(有多少种情况)变量
int count=0;

//记录待放入的结点的前一个结点的坐标(通过函数查找后暂时放在这里)
int iBefTemp=-1,jBefTemp=-1;




															//		______		//
                                                            //				    //
															//		主函数		//
															//					//
															//		~~~~~~		//

int main()
{
	//函数声明
	void befNodePos(int n);
	int checkLine(int i);
	int checkList(int j);
	int checkCorner(int i,int j);
	void print(int a[3][3]);
	int ifCanPut(int i,int j,int n);
	int askIfPrint();
	void putInTurn(int n,int sumNum,int ifPrint);

	//主函数中的变量定义
	int i,sumSolution=0;
	int rememberPrint;

	//确定是否进行打印所有情况
	rememberPrint=askIfPrint();

	for(i=1;i<=9;i++)
	{
		putInTurn(1,i,rememberPrint);
		sumSolution+=count;
		printf("\t当连接%d个点时候有%d种连法\n\t\t累计至此有%d种连法\n\n\n",i,count,sumSolution);	
		count=0;
	}
	printf("\n\n所以,总共有%d种可能的连接方法。\n\n\n",sumSolution);

	return 0;
}



															//		______		//
                                                            //				    //
															//	 其他函数定义	//
															//					//
															//		~~~~~~		//

//找到前一个结点的坐标并将坐标值放置在全局变量iBefTemp和jBefTemp里
void befNodePos(int n)
{
	int i,j;
	for(i=0;i<3;i++)
	{
		for(j=0;j<3;j++)
		{
			if(record[i][j]==n-1)
			{
				iBefTemp=i;
				jBefTemp=j;
				return;
			}

		}

	}

}

//判断间隔位置是否有结点放置。(横向判断)
int checkLine(int i)
{
	if(record[i][1]==0)
		return 0;
	else
		return 1;
}

//判断间隔位置是否有结点放置。(纵向判断)
int checkList(int j)
{
	if(record[1][j]==0)
		return 0;
	else
		return 1;
}

//判断ij位置是否为顶角位置
int checkCorner(int i,int j)
{
	if(i+j==2&&i!=j||i+j==0||i+j==4)
		return 1;
	else
		return 0;
}

//打印的函数
void print(int a[3][3])
{
	int i,j;
	for(i=0;i<3;i++)
	{
		for(j=0;j<3;j++)
		{
			printf("%3d",a[i][j]);
		}
		printf("\n");
	}
	printf("\n");

	getch();
}

//询问是否打印所有情况
int askIfPrint()
{
	int boo;
	printf("\n\n\t\t\t九宫格锁屏程序\n\n");
	printf("你是否想知道每一次的具体连法:\n");
	printf("1.是的,我想看看具体是怎么连的。(提示:情况非常之多)\n");
	printf("2.不,我不必知道具体都是怎么连的,我只想知道有多少种情况。\n\t\t我选择:");

	scanf("%d",&boo);

	if(boo==1)
		return 1;
	else
		return 0;
}


															//		_________________		//
                                                            //								//
															//		判断能否放在ij位置		//
															//								//
															//		~~~~~~~~~~~~~~~~~~		//

int ifCanPut(int i,int j,int n)
{
	//如果这个位置还没有放置结点
	if(record[i][j]==0)
	{
		//找到前一个结点的坐标放在全局变量里面
		//如果是在放置第一个结点,则不必找它的前一个结点,任何一个位置都是合适的。
		if(n==1)
		{
			//因为是放置第一个结点,所以不必判断它跟前一个结点的关系
			return 1;
		}

		//放置除了第一个结点之外的结点,需要判断它个前一个结点的关系。
		else if(n<=9)
		{	
			iBefTemp=-1;
			jBefTemp=-1;
			befNodePos(n);

			//当中间有间隔位置时(横向判断)。
			if(i==iBefTemp&&abs(j-jBefTemp)==2)
			{
				//判断间隔位置是否有结点放置。
				if(checkLine(i))
				{
					//已经有结点
					//////////////可以放置........
					return 1;
				}
				else
				{
					//没有结点放置
					///////////////不能放置在ij这里
					return 0;
				}

			}

			//当中间有间隔位置时(纵向判断)。
			else if(j==jBefTemp&&abs(i-iBefTemp)==2)
			{
				//判断间隔位置是否有结点放置。
				if(checkList(j))
				{
					//已经有结点
					//可以放置.............
					return 1;
				}
				else
				{
					//没有结点
					//////////////不能放置在ij这里
					return 0;
				}

			}

			//当二者为对角关系时
			else if(checkCorner(i,j)&&checkCorner(iBefTemp,jBefTemp)&&(i!=iBefTemp&&j!=jBefTemp))
			{
				//判断中间位置是否有结点放置。
				if(record[1][1]!=0)
				{
					//中间位置已经放置了结点
					//可以放置在ij......
					return 1;
				}
				else
				{
					//中间位置没有放置结点,不能放置在ij
					return 0;
				}	

			}

			//二者中间没有间隔位置,从而可以直接放置。
			else
			{
				//可以放置...........
				return 1;
			}
		}
	}

	//如果这个位置已经放置了结点,不能放置结点
	else
	{
		return 0;
	}
	
}





								
															//		______		//
                                                            //					//
                                                            //		主算法		//
															//					//
															//		~~~~~~		//

void putInTurn(int n,int sumNum,int ifPrint)
{
	int i,j;

	if(n==sumNum+1)
	{
		//已经放置完9个结点,进行计数。
		count++;
		if(ifPrint)
		{
			print(record);
		}

		return;
	}

	//尝试将其放置在i行j列。
	for(i=0;i<3;i++)
	{
		for(j=0;j<3;j++)
		{
			if(ifCanPut(i,j,n))
			{
				record[i][j]=n;
				putInTurn(n+1,sumNum,ifPrint);

				//这个语句很重要!这是递归能否进行的决定性语句。
				record[i][j]=0;
			}

		}

	}

}





                
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值