C语言——解九宫格数独游戏

本文介绍了如何使用C语言实现九宫格数独的解题算法,包括导入题目、检查重复值、填充空格和保存结果的过程,同时提到了如何判断题目是否有解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

九宫格数独,是一个9*9的格子里,填上1-9的数,规则如下:

1.每一行不能有重复的值

2.每一列不能有重复的值

3.每个宫内不能有重复的值

宫的意思是每三个行、列的9个方格为宫

以下为实现代码,有详细的注释:

导入的题目文件名要和代码中“shudutimu.txt”一致,里面的数组格式可以用逗号、顿号、空格,甚至不分隔也可以,代码自动处理成一个81个数的数组。

保存结果的文件自动生成。

#include <stdio.h>

int qw[81];		//导入的题目存放数组 
int aa[81];		//定义一个数组做草稿 
int flag,end;	//数据更改过的标志和结束标志 
int start; 		//起始数据位,用于判断是否可解 

/* 导入题目 */
void qw_load(void)
{
	int ch;
	int n=0;
	FILE* pf = fopen("shudutimu.txt","r");    //导入txt题目文件
	while((ch = fgetc(pf)) != EOF)
	{
		if(ch>='0' && (ch<='9'))
		{
			qw[n]=ch-48;	//ASCII码字符转数字,再放入题目数组 
			n++;
		}
	}
	fclose(pf);
}
/* 保存结果 */
void result(void)
{
	int i,j;
	FILE* pf_rs = fopen("result.txt","w");	//创捷或打开保存结果txt文档 
	if(end==0)	//如果有解,打印结果 
	{
		for(i=0;i<9;i++)
		{
			for(j=0;j<9;j++)
			{
				fprintf(pf_rs, "%d", aa[i*9+j]);
				if(j==2||j==5)
					fprintf(pf_rs, "%s", " | ");
				else
					fprintf(pf_rs, "%s", "  ");
			}
			fprintf(pf_rs, "%s","\n");
			if(i==2||i==5)
				fprintf(pf_rs, "%s","- - - - - - - - - - - - - -\n");
		}
	}
	else
	{
		fprintf(pf_rs, "%s", "此题无解!");
	}
	fclose(pf_rs);	//关闭txt文档 
}
/* 查询当前数字的行、列、宫中有没有重复值 */
void check(int n)
{
	int a,b,i,j;
	int col,row;
	col=n/9;	//一维数组转二维数组的列,就是除以9 
	row=n%9;	//一维数组转二维数组的行,就是9的余数 
	if(aa[n]==0)
	{
		aa[n]=1;	//如果值为0,先赋初值为1,再去判断是否有重复 
	}
	for(a=0;a<9;a++)
	{
		if((col*9+a)!=n)	//查询行中的数据,判断时要避开当前值 
		{
			if(aa[n]==aa[col*9+a])	//如果查询到有重复值 
			{
				aa[n]=aa[n]+1;		//当前值加1 
				flag=1;				//数据更改变为置1,表示已更改过数据
			}						//需要再查询一次,以保证更改后的数据没有重复 
		}
	}
	for(b=0;b<9;b++)
	{
		if((b*9+row)!=n)	//查询列中的数据,和行的处理一样 
		{
			if(aa[n]==aa[b*9+row]) 
			{
				aa[n]=aa[n]+1;
				flag=1;
			}
		}
	}
	for(i=0;i<3;i++)		//查询宫中的数据,和行、列的处理一样 
	{
		for(j=0;j<3;j++)
		{
			if(((col/3*3+i)*9+row/3*3+j)!= n)	//这个除以3再乘以3,看起来有点迷 
			{									//实际上得到的值就是回到当前值所在的宫的第一个数 
				if(aa[n]==aa[(col/3*3+i)*9+row/3*3+j])
				{
					aa[n]=aa[n]+1;
					flag=1;
				}
			}
		}
	}
}
/* 当数据有更改时,再次查询,以确认没有重复值 */
void recheck(int n)
{
	do
	{
		flag=0;
		check(n);
	}while(flag==1);	//只要数据有更改,就一直循环,直到没有更改为止 
}

void fill(int n)
{
	int m;
	m=n;	//保存当前的位置,以便后面退回其他位置更改数据后,判断是否已经回到当前位置 
	do
	{
		recheck(n);		//查询是否有重复值 
		while(aa[n]>9)	//如果查询的结果1-9都重复,一直循环,直到符合1-9为止 
		{
			aa[n]=0;	//则将当前值初始化为0 
			do{
				n--;	//退到上一个位置 
			}while(qw[n]!=0);	//用原始数组来判断上一个位置是否为空缺值,一直退到空缺值位置 
			aa[n]=aa[n]+1;	//把空缺值位置上填的数再往上加 
			recheck(n);		//查询重复值 
			if(n==start && aa[n]>9)	//如果退到首个空缺位置,而且数据加到9了还有重复值 
			{
				aa[n]=0;			//则表示此题无解,将值置0,n置81,就可以退出循环了 
				n=81;				//当然也可以用break退出循环,但是外面还有一层循环 
				end=1;				//结束标志置1,表示此题无解 
			}
		}
		n++;	//退了修改完值之后,再加回来,重新查询重复值 
	}while(n<m+1);	//退回前面位置修改值后,一直循环,直到回到当前位置 
}

int main()
{
	int i,j;
	start=0;
	end = 0;
	qw_load(); 
	/* 题目写入草稿数组 */
	for(i=0;i<81;i++)
	{
		aa[i]=qw[i];
	}
	/* 判断首个空值,用于后面判断题目是否有解 */
	while(aa[start++]!=0);
	start=start-1;
	/* 开始填数 */
	for(i=0;i<81;i++)
	{
		if(aa[i]==0)
		{
			fill(i);
		}
		if(end==1)	//每次填数后,查询是否无解结束
		{
			break;			
		} 
	}
	result();
}

题目:

显示结果:

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值