/*
构造数独:
数独的棋盘是由九九八十一个小方格组成的。玩家在每个小格子中,分别天上1至9的任意一个数字,让整个棋盘每一行,每一列,以及每一个3*3的小矩阵中的数字都不
重复。
使用一个二维数组来存储,每一个元素对应数独中的一个数。但考虑到每一个格子有若干属性,可以把每个格子抽象为一个对象,把整体看成9*9个格子对象
生成游戏初始局面:可以向生成一个完整合法的解,然后再随机地去掉一些数字。
解法1:
假设用下面的结构来存储数独游戏:
int _size = 9;
Cell[,] _cells;
下面的GenerateValidMatrix()函数用经典的深度优先搜索来生成一个可行解。从(0,0)开始,对没有处理过的格子,调用GetValidValueList(coCurrent)来获得当前
格子可能的取值选择,并从中取一个为当前格子的取值,接着搜索下一个格子。在搜索uocheng中,若出现某个格子没有可行的值,则回溯,修改前一个格子的取值。
直到所有的格子都找到可行的取值为止,这是可行解。
没有完成
*/
#include <stdio.h>
#include <string.h>
const int LEN = 9;
int grid[LEN+1][LEN+1];
int visit[LEN+1][LEN+1];
int value[LEN+1];
int go[][2] =
{
{0,-1},//上
{1,0},//右
{0,1},//下
{-1,0}//左
};
bool checkSmallMatrix(int iRow,int iCol)//检查每个小矩阵中是否存在1~9,9个数
{
int iMark[LEN+1];
memset(iMark,0,sizeof(iMark));
for(int i = iRow ; i < iRow + 3 ; iRow++)
{
for(int j = iCol ; j < iCol + 3 ; iCol++)
{
iMark[ grid[i][j] ]++;
}
}
for(int k = 1 ; k <= LEN ; k++)
{
if(iMark[k] != 1)
{
return false;
}
}
return true;
}
bool check()
{
bool isValid = true;
int iMark[LEN+1];
for(int i = 1 ; i <= LEN ; i++)//大数读每一行的检查
{
memset(iMark,0,sizeof(iMark));
for(int j = 1; j <= LEN ; j++)
{
iMark[ grid[i][j] ]++;//正确的情况是每个数字出现的次数为1
}
for(int k = 1 ; k <= LEN ; k++)
{
if(iMark[k] != 1)
{
return false;
}
}
}
for(int j = 1 ; j <= LEN ; j++)//大数读每一列的检查
{
memset(iMark,0,sizeof(iMark));
for(int i = 1; i <= LEN ; i++)
{
iMark[ grid[i][j] ]++;//正确的情况是每个数字出现的次数为1
}
for(int k = 1 ; k <= LEN ; k++)
{
if(iMark[k] != 1)
{
return false;
}
}
}
for(int i = 1 ; i <= LEN ; i += 3)//小数独每个的检查
{
for(int j = 1; j <= LEN ; j += 3)
{
if(checkSmallMatrix(i,j) == false)
{
return false;
}
}
}
return true;
}
void dfs(int x,int y,int pos)//深度优先搜索,首先要设定开始和结束值,剪枝标记,终点是9,9
{
if(x == LEN && y == LEN && check())//如果已经抵达终点,并且符合是数独的条件,那么,输出该数独后结束
{
for(int i = 1 ; i <= LEN ; i++)
{
for(int j = 1 ; j <= LEN ; j++)
{
if(j != 1)
{
printf(" %d",grid[i][j]);
}
else
{
printf("%d",grid[i][j]);
}
}
printf("\n");
}
}
else//递归主体
{
for(int i = 0 ; i < 4 ; i++)
{
int iNewX = x + go[i][0];
int iNewY = y + go[i][1];
if(!visit[iNewX][iNewY] && x >= 1 && x <= LEN && y >= 1 && y <= LEN)//没有访问过,没有越界,就继续向下访问。
//还需要尝试给grid[x][y]进行赋值 ,赋值的元素范围在!~9之间
{
for(int k = pos + 1 ; k <= LEN ; k++)
{
visit[iNewX][iNewY] = 1;
grid[iNewX][iNewY] = k;
dfs(iNewX,iNewY,pos+1);
visit[iNewX][iNewY] = 0;//回溯
grid[iNewX][iNewY] = 0;
}
}
}
}
}
void next(int& x,int& y)
{
x++;
if(x > 9)
{
x = 1;
y++;
}
}
void pre(int& x,int& y)
{
x--;
if(x < 1)
{
x = 9;
y--;
}
}
int pickNextValidValue(int x,int y,int cur)
{
memset(value,0,sizeof(value));
int i,j;
for(i = 1 ; i < y ;i++)
{
value[ grid[i][x] ] = 1;//?
}
for(j = 1 ; j < x ; j++)
{
value[ grid[y][j] ] = 1;//?
}
int u = (x-1)/3*3 + 1;//?
int v = (y-1)/3*3 + 1;
for(i = v; i < v + 3 ; i++)
{
for(j = u ; j < u + 3 ; j++)
{
value[ grid[i][j] ] = 1;//?
}
}
for(i = cur + 1; i <= LEN && value[i] ; i++);
return i;
}
int times = 0;
void process2()
{
int x,y,i,j;
x = y = 1;
//深度优先搜索
while(true)
{
times++;
if(x == LEN && y == LEN)//满足成功结果
{
for(i = 1; i <= LEN ; i++)
{
for(j = 1 ; j <= LEN ; j++)
{
printf("%d ",grid[i][j]);
}
printf("\n%d",times);
break;
}
}
if(y == 0)//满足失败结果
{
break;
}
grid[y][x] = pickNextValidValue(x,y,grid[y][x]);//改变状态
if(grid[y][x] > LEN)//恢复状态
{
grid[y][x] = 0;
pre(x,y);
}
else
{
next(x,y);
}
for(i = 1 ; i <= LEN ; i++)
{
for(j = 1 ; j <= LEN ; j++)
{
printf("%d ",grid[i][j]);
}
printf("\n");
}
}
}
void process()
{
memset(visit,0,sizeof(visit));
visit[1][1] = 1;
dfs(1,1,1);
}
int main(int argc,char* argv[])
{
process2();
getchar();
return 0;
}
//typedef struct Coordinate
//{
// int _iX;
// int _iY;
//}Coordinate;