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

        大学期间,闲来无事,玩数独,发现都是些重复性思维,找缺省值,所以写成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
    评论
数独算法说明:用三个二维数组记录数独每个点的状态,SD(i, j)显示数值,也是真实数值(1到9)。ST(i, j)状态,1可由用户输入,2是题目给定的,不能改。SY(i, j)这符串,记录每个点中可能的值。 1、在进行自动计算时,只计算ST(i, j)为1的点,首先将所有状态为1的点的SY(i, j)值全部设为"123456789",SD(i, j)值全部设为0 2、逐点扫描,找到一个点,然后将该点所在的行、列、区域中已存在的SD(x, y)值从SY(i, j)中删除,因为数独规则是一个数值,在行、列、区域都不重复。 3、经第二步处理后,SY(i, j)为空,说明题目错误,SY(i, j)值为一位数字,就说明该点的值是唯一的,可以确定了。 4、剩余的SY(i, j)值最少也是二个数字的,或更多位数。随机从这些两位数的SY(i, j)中选取一个点。取其中的一位确定为该点的值后,重复第2步。如果错误遇错,则重复执行第4步。直到所有点都被确定。 注意:第2步是需要多次重复执行的,所有可用递归函数完成。如果执行结果出现错误(某数出现重复,或某点无值),需要对该过程所执行的所有操作进行回退。 第4步也是需要重复执行的。本和序用Goto跳转方式实现多次执行。 简单的数独,要么所有的点都具有独一值,第1步执行完成后,就已全部完成。或者具有多个解,随意猜测一个二位数的SY(i, j)的值都能成功。 难的数独,是可唯一确定的点很少,大部分点都有两种或多种可能的值,但最终正确答案只有一种或很少种解。 软件在自动计算过程中,具有很大的偶然性,对于骨灰级的数独题目在计算过程中,时间短的可能不到1秒就能完成,长的可能要几分钟,需要将各种可能性都测试一遍才有结果。 只要题目正确,多计算几次就能得到答案。 程序只处理有两种可能值的情况,对只存在三种可能值的情况未进一步处理,该情况非常极端了。 软件中包含网上下载的200个数独题目。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值