编程之美中构造数独例子

编程之美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;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值