编程之美1.15构造数独
生成一个有效的数独矩阵,只生成一个,可以通过递归将所有有效矩阵都构造出来
#include <stdio.h>
#include <string.h>
#define NO_MOVE 0
#define AC_MOVE 1
#define NUM 9
typedef struct _CELL
{
int type;
int value;
int list[NUM];
int index;
}Cell;
typedef struct _POSITION
{
int x;
int y;
}Position;
Cell m_cells[NUM][NUM]; //构造数独的数组
void GetValidValueList(Cell *c, Position *p)
{
int row[NUM] = {1, 2, 3, 4, 5, 6, 7, 8, 9};//记录行可用数
int column[NUM] = {1, 2, 3, 4, 5, 6, 7, 8, 9};//记录列可用数
int arr[NUM] = {1, 2, 3, 4, 5, 6, 7, 8, 9};//记录小矩阵可用数
int i;
int j;
int tmp;
for(i = 0; i < p->x; i++)//遍历行中已经填的数值,并将其设为0
{
tmp = m_cells[i][p->y].value;
row[tmp - 1] = 0;
}
for(i = 0; i < p->y; i++)//遍历列中已经填的数值,并将其设为0
{
tmp = m_cells[p->x][i].value;
column[tmp - 1] = 0;
}
for(i = p->x - (p->x % 3); i <= p->x; i++)//遍历小矩阵中已经填的数值,并将其设为0
{
for(j = p->y - (p->y % 3); j <= p->y - (p->y % 3) + 2; j++)
{
if(i == p->x && j == p->y)
{
break;
}
tmp = m_cells[i][j].value;
arr[tmp - 1] = 0;
}
}
for(i = 0; i < NUM; i++)
{
c->list[i] = row[i] & column[i] & arr[i];//统计总共可用的数
}
}
int PickNextValidValue(Cell *c)
{
int ret;
while(c->list[c->index] == 0)//跳过不要用的数0,找到一个可用数
{
c->index++;
if(c->index == NUM)
{
break;
}
}
if(c->index < NUM)//判断是否有有效数
{
ret = c->list[c->index];
}
else
{
ret = -1;
}
c->index++;//记录下次选数的位置
return ret;
}
void MoveToNextPosition(Position *p)//移动到下一个点
{
if(p->y == NUM -1)
{
p->y = 0;
p->x += 1;
}
else
{
p->y += 1;
}
}
void MoveToPrePosition(Position *p)
{
if(p->y == 0)
{
p->y = NUM - 1;
p->x -= 1;
}
else
{
p->y -= 1;
}
}
void GenerateValidMatrix()//构造数独
{
Position cur;
int value;
cur.x = 0;
cur.y = 0;
while(1)
{
if(m_cells[cur.x][cur.y].type == NO_MOVE)//如果当前点没有生成可用数列表时,生成该列表
{
GetValidValueList(&m_cells[cur.x][cur.y], &cur);
m_cells[cur.x][cur.y].type = AC_MOVE;
}
value = PickNextValidValue(&m_cells[cur.x][cur.y]);//从可用数列表中选择一个数
if(-1 == value)//如果是无效值,退回前一位置
{
m_cells[cur.x][cur.y].type = NO_MOVE;
m_cells[cur.x][cur.y].index = 0;
MoveToPrePosition(&cur);
}
else
{
m_cells[cur.x][cur.y].value = value;//记录此值
if(cur.x == NUM -1 && cur.y == NUM -1)//判断是否结束
{
break;
}
else
{
MoveToNextPosition(&cur);//移动到下一位置
}
}
}
}
void PrintMatrix()//输出数独矩阵
{
int i;
int j;
for(i = 0; i < NUM; i++)
{
if(i % 3 == 0)
{
printf("\n-------------------------------------\n");
}
else
{
printf("\n");
}
for(j = 0; j < NUM; j++)
{
if(j % 3 == 0)
{
printf("| ");
}
printf("%d ", m_cells[i][j].value);
}
printf("|");
}
printf("\n-------------------------------------\n");
}
int main(int argc, char *argv[])
{
memset(&m_cells, 0, sizeof(m_cells));
GenerateValidMatrix();
PrintMatrix();
return 0;
}