`

解数独程序

阅读更多
// Soduku.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <map>
#include <iostream>
#include <set>
#include <algorithm>
#include <vector>
using namespace std;
#define ROW_NUM (9)
#define COL_NUM (9)
#define NUMBERS (9)
const unsigned char originalArray[ROW_NUM][COL_NUM] = {
	{0,0,0,1,0,0,2,6,0},
	{7,0,0,0,3,0,0,0,0},
	{3,0,2,0,8,0,4,0,0},
	{0,0,0,4,0,8,0,0,1},
	{0,3,5,0,0,0,9,4,0},
	{2,0,0,3,0,5,0,0,0},
	{0,0,6,0,5,0,7,0,9},
	{0,0,0,0,4,0,0,0,8},
	{0,5,7,0,0,9,0,0,0}
};
const unsigned char digits[NUMBERS] = {1,2,3,4,5,6,7,8,9};

struct Grid{
	unsigned char row;
	unsigned char column;
	unsigned char value;
	map<unsigned char, unsigned char> options;
	Grid(){
		row = 0;
		column = 0;
		value = 0;
		options.clear();
	}
};

Grid soduku[ROW_NUM][COL_NUM] = {};

struct NineGrid{
	pair<unsigned char, unsigned char> start;
	pair<unsigned char, unsigned char> end;
	set<unsigned char> values;
	NineGrid(){
		start.first = 0;
		start.second = 0;
		end.first = 0;
		end.second = 0;
		values.clear();
	}
};

NineGrid nineGrid[(ROW_NUM/3)*(COL_NUM/3)] = {};

void InitializeSoduku(){
	for(unsigned char i = 0; i < ROW_NUM; ++i)
	{
		for(unsigned char j = 0; j < COL_NUM; ++j)
		{
			soduku[i][j].row = i;
			soduku[i][j].column = j;
			soduku[i][j].value = originalArray[i][j];
		}
	}
	unsigned char index = 0;
	for(unsigned char i = 0; i < ROW_NUM; i+=3)
	{
		for(unsigned char j = 0; j < COL_NUM; (index++,j+=3))
		{
			nineGrid[index].start.first = i;
			nineGrid[index].start.second = j;
			nineGrid[index].end.first = i+2;
			nineGrid[index].end.second = j+2;
		}
	}
	for(unsigned char n = 0; n < ROW_NUM; ++n)
	{
		for(unsigned char i = nineGrid[n].start.first; i <= nineGrid[n].end.first; ++i)
		{
			for(unsigned char j = nineGrid[n].start.second; j <= nineGrid[n].end.second; ++j)
			{
				if(soduku[i][j].value != 0)
				{
					nineGrid[n].values.insert(soduku[i][j].value);
				}
			}
		}
	}
}
void CollectRow(set<unsigned char>& row, unsigned char rowIndex)
{
	for(unsigned char j = 0; j < COL_NUM; ++j)
	{
		if(soduku[rowIndex][j].value != 0)
		{
			row.insert(soduku[rowIndex][j].value);
		}
	}
}
void CollectColumn(set<unsigned char>& col, unsigned char colIndex)
{
	for(unsigned char i = 0; i < ROW_NUM; ++i)
	{
		if(soduku[i][colIndex].value != 0)
		{
			col.insert(soduku[i][colIndex].value);
		}
	}
}
void CollectNineGrid(set<unsigned char>& gridSet,unsigned char row, unsigned char col)
{
	for(unsigned int i = 0; i < ROW_NUM; ++i)
	{
		if(nineGrid[i].start.first <= row && row <= nineGrid[i].end.first)
		{
			if(nineGrid[i].start.second <= col && col <= nineGrid[i].end.second)
			{
				for(unsigned char m = nineGrid[i].start.first; m <= nineGrid[i].end.first; ++m )
				{
					for(unsigned char n = nineGrid[i].start.second; n <= nineGrid[i].end.second; ++n)
					{
						if(soduku[m][n].value != 0)
						{
							gridSet.insert(soduku[m][n].value);
						}
					}
				}
				break;
			}
		}
	}
}
void CollectAll(set<unsigned char>& vals,unsigned char row, unsigned char col)
{
	vals.clear();
	CollectRow(vals, row);
	CollectColumn(vals, col);
	CollectNineGrid(vals, row, col);
}
void PrintCurrent()
{
	for(unsigned char i = 0; i < ROW_NUM; ++i)
	{
		for(unsigned char j = 0; j < COL_NUM; ++j)
		{
			if(soduku[i][j].value == 0)
			{
				cout<<"(";
				std::map<unsigned char, unsigned char>::iterator iter = soduku[i][j].options.begin();
				for(iter; iter !=  soduku[i][j].options.end(); ++iter)
				{
					cout<<(unsigned short)iter->second<<",";
				}
				cout<<")";
			}else
			{
				cout<<(unsigned short)soduku[i][j].value<<" ";
			}
			
		}
		cout<<std::endl;
	}
}
bool HasExisted(std::set<unsigned char>& values, unsigned char val)
{
	return values.find(val) != values.end();
}
void DigitsLoop()
{
	for(unsigned char m = 0; m < NUMBERS; ++m)
	{
		unsigned char digit = digits[m];
		for(unsigned char n = 0; n < ROW_NUM; ++n)
		{
			for(unsigned char i = nineGrid[n].start.first; i <=  nineGrid[n].end.first; ++i)
			{
				for(unsigned char j = nineGrid[n].start.second; j <= nineGrid[n].end.second; ++j)
				{
					if(soduku[i][j].value != 0)
					{
						continue;
					}
					set<unsigned char> values;
					do
					{	//验证九宫格中的数
						values.clear();
						CollectNineGrid(values, i, j);
						if(HasExisted(values, digit))
						{
							break;
						}
						//验证横排
						values.clear();
						CollectRow(values, i);
						if(HasExisted(values, digit))
						{
							break;
						}
						//验证竖排
						values.clear();
						CollectColumn(values, j);
						if(HasExisted(values, digit))
						{
							break;
						}

						soduku[i][j].options[digit] = digit;
					}while(0);
				}
			}
		}
	}
}

void AddToNineGridSet(unsigned char row, unsigned char col, unsigned char val)
{
	for(unsigned int i = 0; i < ROW_NUM; ++i)
	{
		if(nineGrid[i].start.first <= row && row <= nineGrid[i].end.first)
		{
			if(nineGrid[i].start.second <= col && col <= nineGrid[i].end.second)
			{
				nineGrid[i].values.insert(val);
				break;
			}
		}
	}
}
void RemoveAll(unsigned char row, unsigned char col, unsigned char val)
{
	//1.去除行中其他空格可选项中val对应的项目
	std::map<unsigned char, unsigned char>::iterator iter;
	for(unsigned char j = 0; j < COL_NUM; ++j)
	{
		if(soduku[row][j].options.empty())
		{
			continue;
		}
		iter = soduku[row][j].options.find(val);

		if(iter != soduku[row][j].options.end())
		{
			soduku[row][j].options.erase(iter);
		}
	}
	//2.去除列中其他空格可选项中val对应的项目
	for(unsigned int i = 0; i < ROW_NUM; ++i)
	{
		if(soduku[i][col].options.empty())
		{
			continue;
		}
		iter = soduku[i][col].options.find(val);

		if(iter != soduku[i][col].options.end())
		{
			soduku[i][col].options.erase(iter);
		}
	}
	//3.去除九宫格中其他空格可选项中val对应的项目
	for(unsigned int i = 0; i < ROW_NUM; ++i)
	{
		if(nineGrid[i].start.first <= row && row <= nineGrid[i].end.first)
		{
			if(nineGrid[i].start.second <= col && col <= nineGrid[i].end.second)
			{
				for(unsigned char m = nineGrid[i].start.first; m <= nineGrid[i].end.first; ++m )
				{
					for(unsigned char n = nineGrid[i].start.second; n <= nineGrid[i].end.second; ++n)
					{
						if(soduku[m][n].options.empty())
						{
							continue;
						}
						iter = soduku[m][n].options.find(val);

						if(iter != soduku[m][n].options.end())
						{
							soduku[m][n].options.erase(iter);
						}
					}
				}
				break;
			}
		}
	}
}
void MakeChoice()
{
	for(unsigned char i = 0; i < ROW_NUM; ++i)
	{
		for(unsigned char j = 0; j < COL_NUM; ++j)
		{
			if(soduku[i][j].options.size() == 1)
			{
				//赋值给对应的空格
				soduku[i][j].value = soduku[i][j].options.begin()->first;
				//加入九宫格中的集合中
				AddToNineGridSet(i, j, soduku[i][j].value);
				//去除横列和九宫格中其他空格可选项中含有该值的项目
				RemoveAll(i, j, soduku[i][j].value);
			}
		}
	}
}
void Exception()
{
	set<unsigned char> vals;
	
	for(unsigned char i = 0; i < ROW_NUM; ++i)
	{
		for(unsigned char j = 0; j < COL_NUM; ++j)
		{
			if(soduku[i][j].value != 0)
			{
				continue;
			}
			CollectAll(vals, i, j);
			vector<unsigned char> result(10);
			std::set_difference(digits, digits+NUMBERS, vals.begin(), vals.end(), result.begin());

			for(unsigned int n = 0; n < result.size(); ++n)
			{
				if(result[n] != 0)
				{
					soduku[i][j].options[result[n]] = result[n];
				}
			}
		}
	}
}
bool CanEnd()
{
	for(unsigned char i = 0; i < ROW_NUM; ++i)
	{
		for(unsigned char j = 0; j < COL_NUM; ++j)
		{
			if(soduku[i][j].value == 0)
			{
				return false;
			}
		}
	}

	return true;
}

int _tmain(int argc, _TCHAR* argv[])
{
	InitializeSoduku();
	do
	{
		DigitsLoop();
		MakeChoice();
		Exception();
		MakeChoice();
		
	}while(!CanEnd());

	PrintCurrent();

	getchar();

	return 0;
}

 

分享到:
评论

相关推荐

    解数独程序 解数独 DFS搜索

    解数独程序 解数独 DFS搜索

    python实现解数独程序代码

    下面就记录一下我写解数独程序的一些思路和心得。 一.数独游戏的基本解决方法 编程笼统的来说,就是个方法论。不论什么程序,都必须将问题的解决过程分解成计算机可以实现的若干个简单方法。俗话说,大道至简。对于...

    c语言回溯解数独程序

    通过以上步骤,我们可以编写出一个简单的C语言回溯解数独程序。这种程序不仅易于理解和实现,而且由于C语言的效率,其运行速度也相当不错。对于学习算法和数据结构的学生来说,这是一个很好的练习项目,有助于提升...

    一个解数独的程序

    1. **算法基础**:解数独程序的核心是算法,常见的算法有深度优先搜索(DFS)和回溯法。这两种算法都是通过尝试填充数字并检查是否符合规则,如果不符则回溯到上一步,尝试其他可能性。此外,还有更优化的算法如“X-...

    使用php开发的解数独程序

    在本文中,我们将深入探讨如何使用PHP开发一个解数独程序。数独是一种逻辑游戏,玩家需要通过填充一个9x9的网格,使得每一行、每一列以及每一个3x3的小宫格都包含数字1到9,且每个数字在各自的行、列和小宫格内仅...

    穷举式解数独程序

    在运行目录先建一个Sudoku.txt 文件将数独输入文件中运行程序即可。本程序用递归 穷举法解答数独。输入txt文件中数据格式: 0 7 0 0 0 0 0 0 0 5 0 3 0 0 6 0 0 0 0 6 2 0 8 0 7 0 0 0 0 0 3 0 2 0 5 0 0 0 4 0 1 0 ...

    C语言解数独程序:贪心+递归

    在解数独的过程中,贪心算法可以用于填充那些只有一种可能答案的单元格,即当某单元格所在的行、列和小宫格中只剩下一个未使用的数字时,我们可以直接填入。 然而,仅靠贪心算法不能解决所有数独问题,因为有些情况...

    解数独 数独游戏 DFS搜索

    解数独程序源码

    Matlab解数独的程序

    标题中的"Matlab解数独的程序"指的是使用MATLAB语言编写的算法,该算法可以自动解决数独难题。这样的程序通常会采用回溯法或深度优先搜索(DFS)策略,通过递归地填充空格并检查每一步的合法性来寻找唯一的解决方案...

    解数独C程序

    在给定的标题“解数独C程序”中,我们可以理解这是一份使用C语言编写的程序,它的目的是解决数独问题。 C语言是一种基础且高效的编程语言,常用于系统级编程和开发嵌入式系统。在这个项目中,我们可能会看到如何...

    解数独C源码

    自己写的C语言版的解数独程序,该死的字数限制

    C语言解数独程序的

    C语言解数独程序的源码解释 在本文中,我们将详细介绍C语言解数独程序的源码,主要包括程序的结构、变量定义、函数实现和算法分析等方面的内容。 程序结构 程序的结构主要包括头文件的包含、常量定义、结构体定义...

    解数独的C++程序

    本项目是一个使用C++编程语言编写的解数独程序,它通过栈数据结构来实现数独的搜索和求解。 首先,我们要理解C++中的栈(Stack)是一种后进先出(LIFO,Last In First Out)的数据结构,常用于回溯算法中。在这个...

    java解数独

    在提供的文件列表中,“破解九宫格”可能是指一个具体的数独实例,或者是解数独程序的测试用例。它可能是以文本文件的形式存储,每行9个数字表示数独的一个宫格,空格表示未知数字,需要通过程序来填充。 综上所述...

    MATLAB 解数独

    本文将深入探讨如何使用MATLAB来编写一个解数独的程序,以及递归调用在其中的作用。 首先,我们要理解数独的基本规则。数独盘面是一个9x9的网格,分为9个3x3的小宫格,每个宫格、每一行、每一列都必须包含数字1到9...

    解数独工具

    "解数独工具.exe"是这个程序的执行文件,用户可以通过双击运行来启动工具。而"使用说明.txt"则包含了如何操作和使用该工具的详细步骤和提示,包括如何加载数独谜题、如何启用自动解决功能、如何查看解题步骤等。对于...

    自动解数独

    自动解数独程序,自己写的使用的VB2010,打不开的请先安装.net4.0,源代码在另一个下载里

Global site tag (gtag.js) - Google Analytics