《数独》游戏自动填充运算

        大学期间,闲来无事,玩数独,发现都是些重复性思维,找缺省值,所以写成c++代码自动填充,可破解多种难度《数独》试题,彻底解决烧脑游戏中的计算量大,计算过程复杂,徒手计算易出差错的问题。

#include<iostream>
#include<stdio.h>
#include<memory.h>
using namespace std;
short sd[9][9],sdw[9][9];
int count;
//short i,j;
short i1=0;
short a[9][12];
void Initialize()
{
	short i,j;
	for(i=0;i<9;i++)
		for(j=0;j<9;j++)
			sdw[i][j]=0x1ff;
}
void input()
{
	short i,j;
	for(i=0;i<9;i++)
	{
		for(j=0;j<9;j++)
		{
			cin>>sd[i][j];
			if(0==sd[i][j])
				count++;
		}
		if(i<8)
			cout<<i+1<<")Please input next line!"<<endl;
	}
	cout<<"Input to complete!"<<endl;
}
void output()
{
	short i,j;
	char buf[50]={0};
	for(i=0;i<9;i++)
	{
		for(j=0;j<9;j++)
		{
//			sprintf(buf,"sd[%d][%d]=%x ",i,j,sd[i][j]);
			cout<<sd[i][j]<<" ";
		}
		cout<<endl;
	}
	for(i=0;i<9;i++)
	{
		for(j=0;j<9;j++)
		{
			sprintf(buf,"%3x ",sdw[i][j]);
			cout<<buf<<" ";
		}
		cout<<endl;
	}
}
void coding()
{
	short i,j;
	for(i=0;i<9;i++)
		for(j=0;j<9;j++)
			switch(sd[i][j])
			{
			case 1:sd[i][j]=0x01;break;
			case 2:sd[i][j]=0x02;break;
			case 3:sd[i][j]=0x04;break;
			case 4:sd[i][j]=0x08;break;
			case 5:sd[i][j]=0x10;break;
			case 6:sd[i][j]=0x20;break;
			case 7:sd[i][j]=0x40;break;
			case 8:sd[i][j]=0x80;break;
			case 9:sd[i][j]=0x100;break;
			default:sd[i][j]=0x00;
			}
}
void decode()
{
	short i,j;
	for(i=0;i<9;i++)
		for(j=0;j<9;j++)
			switch(sd[i][j])
		{
			case 0x01:sd[i][j]=1;break;
			case 0x02:sd[i][j]=2;break;
			case 0x04:sd[i][j]=3;break;
			case 0x08:sd[i][j]=4;break;
			case 0x10:sd[i][j]=5;break;
			case 0x20:sd[i][j]=6;break;
			case 0x40:sd[i][j]=7;break;
			case 0x80:sd[i][j]=8;break;
			case 0x100:sd[i][j]=9;break;
			default:sd[i][j]=0;
		}
}
short bitor(short sddbuf[9])
{
	short bit=0;
	for(short i=0;i<9;i++)
		bit|=sddbuf[i];
	return (bit^0x1ff);
//		cout<<sddbuf[i]<<" ";

}
void numOK()
{
	short i,j;
	for(i=0;i<9;i++)
		for(j=0;j<9;j++)
			if(sdw[i][j]!=0x1ff)
				for(short bitmove=0x100;bitmove!=0;bitmove>>=1)
					if(0==(bitmove^sdw[i][j]))
					{	sd[i][j]=sdw[i][j];
						sdw[i][j]=0x1ff;
						count--;
					}
}
void store9x12(short ii,short jj,short bit11)
{
//	short i1=0;应定义一个全局的
	short j1=1;
	//========
	/*if(ii==6&&jj==6)
	{
		cout<<"ok"<<endl;
	}*/
	//========
	if(0==sd[ii][jj])
	{
		sdw[ii][jj]&=bit11;
		a[i1][0]=sdw[ii][jj];
		a[i1][10]=ii;
		a[i1][11]=jj;
		for(short bitmove=0x100;bitmove!=0;bitmove>>=1)
			a[i1][j1++]=a[i1][0]&bitmove;
		i1++;
	}
}
void ONE()
{
	short i2=0,j2=0,i3=0;
	short k=0,line=0;
	for(j2=1;j2<10;j2++)
	{
		for(i2=0;i2<i1;i2++)
			if(a[i2][j2]!=0)
			{
				k++;
				if(k==1)
					line=i2;
				if(k>1)
					break;
			}
		if(k==1)
		{
			sdw[a[line][10]][a[line][11]]=a[line][j2];
			a[line][0]=a[line][j2];
			for(i3=1;i3<10;i3++)
				a[line][i3]=0;
		}
		k=0;
	}
}
void TWO()
{
	short aa[40][4]={0};
	short i7=0,i5,i4;
	for(i5=0;i5<i1-1;i5++)
		for(i4=i5+1;i4<i1;i4++)
		{
			aa[i7][0]=a[i5][0]&a[i4][0];
			aa[i7][2]=i4;
			aa[i7][3]=i5;
			for(short bitmove=0x100;bitmove!=0;bitmove>>=1)
				if(bitmove&aa[i7][0])
					aa[i7][1]++;
			if(aa[i7][1]==2)
			{
				if(a[i5][0]==a[i4][0])
				{
					short i8=0;
					while(i8<i1)
					{
						if(i8!=i5&&i8!=i4)
						{
							a[i8][0]=~aa[i7][0]&a[i8][0];
							sdw[a[i8][10]][a[i8][11]]=~aa[i7][0]&sdw[a[i8][10]][a[i8][11]];
						}
						i8++;
					}
				}//取反相与
				else
				{
					short i6=0;
					while(i6<i1)
					{if(aa[i7][0]&a[i6][0])
						break;
					i6++;
					if(i6==aa[i7][2]&&i6==aa[i7][3])
						i6++;
					}
					if(i6==i1)
					{
						a[aa[i7][2]][0]=aa[i7][0];
						a[aa[i7][3]][0]=aa[i7][0];
						sdw[a[aa[i7][2]][10]][a[aa[i7][2]][10]]=aa[i7][0];
						sdw[a[aa[i7][3]][10]][a[aa[i7][3]][10]]=aa[i7][0];
					}
				}//赋两值
				i7++;
			}
			else	
			{
				i7++;
//				continue;
			}
		}
}
void line0()
{
	short i,j;
	short bit1=0;
	for(i=0;i<9;i++)
	{
		bit1=bitor(sd[i]);
		if(bit1==0x1ff)
			continue;
		i1=0;
		memset(a,0,sizeof(a));
		for(j=0;j<9;j++)
			store9x12(i,j,bit1);
		if(i1>2)
		{
		ONE();
		TWO();
		}
	}
}
void rank0()
{
	short i,j;
	short sdbuf[9]={0};
	short bit1=0;
	for(j=0;j<9;j++)
	{
		for(int x=0;x<9;x++)
			sdbuf[x]=sd[x][j];
		bit1=bitor(sdbuf);
		if(bit1==0x1ff)
			continue;
		i1=0;
		memset(a,0,sizeof(a));
		for(i=0;i<9;i++)
			store9x12(i,j,bit1);
		if(i1>2)
		{
		ONE();
		TWO();
		}
	}
}
void block0()
{
	short i,j;
	short sdbuf[9]={0};
	short bit1=0;
	short m=0,n=0,y=0;
	for(i=0;i<9;i+=3)
		for(j=0;j<9;j+=3)
		{
			for(m=i;m<i+3;m++)
				for(n=j;n<j+3;n++)
					sdbuf[y++]=sd[m][n];
			y=0;
			bit1=bitor(sdbuf);
			if(bit1==0x1ff)
				continue;
			i1=0;
			memset(a,0,sizeof(a));
			for(m=i;m<i+3;m++)
				for(n=j;n<j+3;n++)
					store9x12(m,n,bit1);  //1/9块内九宫格空位填充拷贝啊a[9][12]完毕
			if(i1>2)
			{
			ONE();
			TWO();
			}//添加特殊情况处理算法
		}
}
void main()
{
	int subcnt;
	Initialize();
	input();
	coding();
	while(1)
	{
		subcnt=count;
		line0();
		numOK();
		rank0();
		numOK();
		block0();
		numOK();
		if(subcnt==count||count==0)
			break;
	}
	decode();
	output();
	cout<<"Mrbai good"<<endl;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
一、数独说明:数独由九行,九列组成,又分为顺序排列的九宫。每行、每列及每宫都包含九个格,九个格中填放1到9的不重复的数字。 二、自动计算原理(三步法): 1、基础法:找出空格中唯一可填的数字。方法是,先假设某空格中可填入九个数字,然后去掉所在行、所在列、所在宫中的已有数字。余下如果是唯一一个数字,那么这个数字就是结果 2、找唯一法:例如果某行、某列或某宫中只剩一个空格,那么九个数字中缺少的那个就是结果。 3、求唯余法:对于存在多个可能值的空格,循环取其中一个作为假设值,然后反复利用方法1和方法2去测试,如果出错冲突或导致别的空格无值可填时,说明假设的值是错误的。并对别剩余未找到唯一值的空格进行同样操作,直至找到可行的一个方案。 三、自动出题,是自动求解的反向过程,先给出答案,再组合题目: 1、数独难易程度跟数独已知的数字个数有一定关系,但不是必然关系。可分为四级,根据网友“数独难度分级”的文章https://wenku.baidu.com/view/af550ed51a37f111f1855ba0.html,结果是分布在0到1之间的一系列值,值越少越容易。 2、出题时,先利用随机数往81个空格中填入不冲突的值。方法是,因为对角线的三宫中的数字互不干扰,用随机数填充这三宫,然后根据数独规则要求随机填入另外六宫。 3、这是最终结果,然后根据难易要求,随机将结果中的一定数量(可以用随机数)的方格清空。数独题已经形成。再根据网友提供的级别计算公式,计算形成的数独题的难易程度是否符合要求。(此时的数独答案不是唯一的) 4、难易程度具体计算公式是:两个空格所有可能值如果有依赖关系值为1,没依赖关系值为0。如此汇总所有空格之间的关系值为A,再除以空格个数B的18倍。即A/(18*B)。0—0.25为0级,0.25—0.5为1级,0.5—0.75为2级,0.75—1为3组。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值