#include<iostream>
#include<iomanip>
using namespace std;
#define MaxSize 81 //用于表示队列的长度
class Grid
{
public:
Grid(int i=0x000901FF):item(i){}
int getNum(){ return (item>>16); } //返回这个Grid的可能值的个数
int getItem(){ return (item&0x0000FFFF); }
int ItemtoNum() {
int i;
int temp = item;
for(i=0; i<8 ; i++)
{
if(temp&0x1)
break;
temp>>=1;
}
return (i+1)%10;
}
int del(int i){ item&=~int(i); return _setNum(); } //注意这里的i为二进制形式
int add(int i){ item|= int(i); return _setNum(); } //注意这里的i为二进制形式
int set(int i){ item=0; return add(i); } //i同上, 这个函数用于设置数值
private:
int item;
int _setNum() { //数出可能值的个数, 并赋值
int temp = item;
int r = temp&0x1;
for(int i=0; i<8; i++){
temp>>=1;
r += temp&0x1;
}
item&=0x0000FFFF;
item|= r<<16;
return r;
}
};
class JiugongGe
{
public:
JiugongGe(Grid* igrd=NULL){
if(igrd!=NULL)
for(int i=0; i<9; i++){
grd[i] = igrd[i];
if(grd[i].getNum() == 1){ //设置表
// setJiugongGe(i);
}
}
}
Grid& getGrid(int i, int j){ return grd[i*3+j]; } //用于大九宫格的寻址
Grid& getGrid(int i) { return grd[i]; }
//void setJiugongGe(int i){
// item+=0x00010000; //数字加一
// item|=int(1<<(i-1)); //表明位置;
//}
private:
// int item; //去除
Grid grd[9];
};
template<class T>
class Queue // 用于存放Grid的一些信息
{
public:
Queue():size(0){}
void Enter(T t){ item[size++] = t; }
T operator[](int i) { if(i>=0 && i<size) return item[i]; }
int getSize() { return size; }
void clear() { size=0; }
private:
int size;
T item[MaxSize];
};
///消息结构
struct Info
{
int px;
int py;
int item;
Info(int i=-1, int j=-1, int n=-1):px(i), py(j), item(n){}
};
class Sudoku
{
public:
Sudoku(Sudoku* sdk=NULL){
if(sdk!=NULL){
for(int i=0; i<9; i++){
jgg[i] = sdk->jgg[i];
}
}
else{
for(int i=0; i<9; i++)
jgg[i] = new JiugongGe;
}
}
~Sudoku(){
for(int i=0; i<9; i++)
delete jgg[i];
}
Grid** getLine(int type, int n)
{
Grid** temp = new Grid*[9];
switch(type)
{
case 1:
for(int i=0; i<3; i++){
for(int j=0; j<3; j++){
temp[i*3+j] = &jgg[3*(n/3)+i]->getGrid(n%3,j);
}
}
break;
case 2:
for(int i=0; i<3; i++){
for(int j=0; j<3; j++){
temp[i*3+j] = &jgg[n/3+i*3]->getGrid(j,n%3);
}
}
break;
case 3:
for( int i=0; i<9; i++)
temp[i] = &jgg[n]->getGrid(i);
break;
}
return temp;
}
Grid& getGrid(int i, int j)
{
return jgg[3*(i/3)+j/3]->getGrid(i%3, j%3);
}
void setGrid(int i, int j, int value) //value 为数字
{
getGrid(i, j).set(int(1)<<(value-1));
}
void setGrid(int type, int n, int i, int value) //value 为数字
{
switch(type)
{
case 1:
setGrid(n, i, value);
break;
case 2:
setGrid(i, n, value);
break;
case 3:
setGrid(3*(n/3)+i/3, 3*(n%3)+i%3, value);
break;
}
}
void run()
{
//程序的初始化, 用于查找确定的Grid, 同时填写信息队列
for(int i=0; i<9; i++){
for(int j=0; j<9; j++){
Grid temp = getGrid(i,j);
if(temp.getNum()==1)
info.Enter(Info(i,j,temp.getItem()));
}
}
//初始化结束, 进行运行, 从信息队列中取出信息,
//然后设置影响的行列及九宫格,同时填写信息队列
while(info.getSize()){
while(info.getSize()){
Queue<Info> T_info = info;
info.clear();
for( int type=1; type<=3; type++){
for(int i=0; i<9; i++){
int item;
if(item = getDelItem(T_info, type, i))
del(type, i, item);
}
}
}
// Grid testt = getGrid(5,1);
// Grid& testt = getGrid(0,3);
//需求处理
for(int type=1; type<=3; type++){
for(int i=0; i<9; i++){
makeItem(type, i);
}
}
}
}
void del(int type, int n, int item)
{
Grid** grid = getLine(type, n);
for( int i=0; i<9; i++){
if(grid[i]->getNum() == 1)
continue;
if(grid[i]->del(item) == 1)
EnterInfo(type, n, i, grid[i]->getItem());
}
}
/* **************************************************
* 函数功能: 在给定的一个数组中,根据需求法确定元素,
* 并存入Info数组;
*
* 参数说明: type : 1 表示行
* : 2 表示列
* : 3 九宫格
* num 表示第几 行、列、九宫格
* grid 传入的数组
*
****************************************************/
void makeItem(int type, int num )
{
///test
// Grid& testt = getGrid(5,1);
Grid** grid = getLine(type, num);
for(int i=0; i<9; i++){
int f = int(1)<<i;
int n=0, k=0;
for(int j=0; j<9; j++){
if(grid[j]->getItem()&f){
k=j;
n++;
}
}
if( n==0)
exit(1); //出错啦!、、、、、、、、、、、、、、、、、
if( n==1 && grid[k]->getNum()!=1 )
{
setGrid(type, num, k, i+1); //此中的i+1应为数字, 而非符号
EnterInfo(type, num, k, f); //此中 f 为符号
}
}
}
void EnterInfo(int type, int n, int i, int item)
{
switch (type)
{
case 1:
info.Enter(Info(n, i, item));
break;
case 2:
info.Enter(Info(i, n, item));
break;
case 3:
info.Enter(Info(3*(n/3)+i/3, 3*(n%3)+i%3, item));
break;
}
}
/* **************************************************
* 函数功能: 在Queue中获取 行、列、九宫格中相应要
* 减去的项
* 参数说明: type : 1 表示行
* : 2 表示列
* : 3 九宫格
* num 表示第几 行、列、九宫格
*
****************************************************/
int getDelItem(Queue<Info>& info,int type, int num)
{
int r;
switch(type)
{
case 1:
r=getRowItem(info, num);
break;
case 2:
r=getColumnItem(info, num);
break;
case 3:
r=getJiugongGeItem(info, num);
break;
}
return r;
}
int getRowItem(Queue<Info>& info, int num)
{
int r=0;
for(int i=0; i<info.getSize(); i++){
Info temp = info[i];
if(temp.px == num)
r |= temp.item;
}
return r;
}
int getColumnItem(Queue<Info>& info, int num)
{
int r=0;
for(int i=0; i<info.getSize(); i++){
Info temp = info[i];
if(temp.py == num)
r |= temp.item;
}
return r;
}
int getJiugongGeItem(Queue<Info>& info, int num)
{
int r=0;
for(int i=0; i<info.getSize(); i++){
Info temp = info[i];
if(temp.px>=3*(num/3) && temp.px<3*(num/3+1)
&& temp.py>=3*(num%3) && temp.py<3*(num%3+1))
r |= temp.item;
}
return r;
}
//运行九宫格
void print();
private:
Queue<Info> info; //用于存放确定的Grid 的信息
// int cItem[9], rItem[9]; //去除
JiugongGe* jgg[9];
};
void Sudoku::print()
{
for( int i=0; i<9; i++){
Grid** temp = getLine(1,i);
for( int j=0; j<9; j++)
cout << setw(2) << ((temp[j]->getNum()==1) ? temp[j]->ItemtoNum(): 0);
cout << endl;
}
}
///test/
void test()
{
Sudoku jw;
/*jw.setGrid(0,2,3);
jw.setGrid(0,4,5);
jw.setGrid(0,7,1);
jw.setGrid(1,2,8);
jw.setGrid(1,4,7);
jw.setGrid(1,6,3);
jw.setGrid(2,1,2);
jw.setGrid(2,4,3);
jw.setGrid(3,1,1);
jw.setGrid(3,3,9);
jw.setGrid(3,5,2);
jw.setGrid(3,8,4);
jw.setGrid(4,2,6);
jw.setGrid(4,4,8);
jw.setGrid(4,6,1);
jw.setGrid(5,0,2);
jw.setGrid(5,5,4);
jw.setGrid(5,7,3);
jw.setGrid(6,4,4);
jw.setGrid(6,7,5);
jw.setGrid(7,2,7);
jw.setGrid(7,4,9);
jw.setGrid(7,6,8);
jw.setGrid(8,1,6);
jw.setGrid(8,4,2);
jw.setGrid(8,6,9);
jw.setGrid(0, 1, 4);
jw.setGrid(0, 3, 2);
jw.setGrid(0, 6, 8);
jw.setGrid(1, 2, 1);
jw.setGrid(1, 6, 9);
jw.setGrid(2, 0, 6);
jw.setGrid(2, 5, 4);
jw.setGrid(3, 2, 6);
jw.setGrid(3, 4, 1);
jw.setGrid(3, 7, 7);
jw.setGrid(4, 0, 1);
jw.setGrid(4, 4, 2);
jw.setGrid(4, 8, 4);
jw.setGrid(5, 1, 7);
jw.setGrid(5, 6, 3);
jw.setGrid(6, 3, 7);
jw.setGrid(6, 8, 3);
jw.setGrid(7, 2, 8);
jw.setGrid(7, 6, 2);
jw.setGrid(8, 2, 5);
jw.setGrid(8, 5, 3);
jw.setGrid(8, 7, 9);*/
// jw.print();
jw.setGrid(0,0,6);
jw.setGrid(0,4,9);
jw.setGrid(0,6,1);
jw.setGrid(0,8,4);
jw.setGrid(1,0,1);
jw.setGrid(1,1,9);
jw.setGrid(1,3,7);
jw.setGrid(1,6,2);
jw.setGrid(2,1,8);
jw.setGrid(2,3,4);
jw.setGrid(2,4,3);
jw.setGrid(2,6,5);
jw.setGrid(3,2,6);
jw.setGrid(3,4,2);
jw.setGrid(3,5,7);
jw.setGrid(3,6,3);
jw.setGrid(3,8,1);
jw.setGrid(4,2,7);
jw.setGrid(4,5,4);
jw.setGrid(4,6,9);
jw.setGrid(5,0,3);
jw.setGrid(5,2,8);
jw.setGrid(5,5,5);
jw.setGrid(5,6,4);
jw.setGrid(6,2,9);
jw.setGrid(6,4,7);
jw.setGrid(6,5,2);
jw.setGrid(6,7,1);
jw.setGrid(7,2,1);
jw.setGrid(7,5,9);
jw.setGrid(7,7,4);
jw.setGrid(7,8,5);
jw.setGrid(8,0,8);
jw.setGrid(8,2,5);
jw.setGrid(8,4,4);
jw.setGrid(8,8,2);
jw.run();
jw.print();
// jw.run();
}
void main()
{
test();
/*Grid jw(0x30007);
cout << jw.getNum() << " " << jw.getItem() << endl;
jw.del(2);
cout << jw.getNum() << " " << jw.getItem();*/
}
数独源代码
最新推荐文章于 2024-05-28 08:45:00 发布