// 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搜索
下面就记录一下我写解数独程序的一些思路和心得。 一.数独游戏的基本解决方法 编程笼统的来说,就是个方法论。不论什么程序,都必须将问题的解决过程分解成计算机可以实现的若干个简单方法。俗话说,大道至简。对于...
通过以上步骤,我们可以编写出一个简单的C语言回溯解数独程序。这种程序不仅易于理解和实现,而且由于C语言的效率,其运行速度也相当不错。对于学习算法和数据结构的学生来说,这是一个很好的练习项目,有助于提升...
1. **算法基础**:解数独程序的核心是算法,常见的算法有深度优先搜索(DFS)和回溯法。这两种算法都是通过尝试填充数字并检查是否符合规则,如果不符则回溯到上一步,尝试其他可能性。此外,还有更优化的算法如“X-...
在本文中,我们将深入探讨如何使用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 ...
在解数独的过程中,贪心算法可以用于填充那些只有一种可能答案的单元格,即当某单元格所在的行、列和小宫格中只剩下一个未使用的数字时,我们可以直接填入。 然而,仅靠贪心算法不能解决所有数独问题,因为有些情况...
解数独程序源码
标题中的"Matlab解数独的程序"指的是使用MATLAB语言编写的算法,该算法可以自动解决数独难题。这样的程序通常会采用回溯法或深度优先搜索(DFS)策略,通过递归地填充空格并检查每一步的合法性来寻找唯一的解决方案...
在给定的标题“解数独C程序”中,我们可以理解这是一份使用C语言编写的程序,它的目的是解决数独问题。 C语言是一种基础且高效的编程语言,常用于系统级编程和开发嵌入式系统。在这个项目中,我们可能会看到如何...
自己写的C语言版的解数独程序,该死的字数限制
C语言解数独程序的源码解释 在本文中,我们将详细介绍C语言解数独程序的源码,主要包括程序的结构、变量定义、函数实现和算法分析等方面的内容。 程序结构 程序的结构主要包括头文件的包含、常量定义、结构体定义...
本项目是一个使用C++编程语言编写的解数独程序,它通过栈数据结构来实现数独的搜索和求解。 首先,我们要理解C++中的栈(Stack)是一种后进先出(LIFO,Last In First Out)的数据结构,常用于回溯算法中。在这个...
在提供的文件列表中,“破解九宫格”可能是指一个具体的数独实例,或者是解数独程序的测试用例。它可能是以文本文件的形式存储,每行9个数字表示数独的一个宫格,空格表示未知数字,需要通过程序来填充。 综上所述...
本文将深入探讨如何使用MATLAB来编写一个解数独的程序,以及递归调用在其中的作用。 首先,我们要理解数独的基本规则。数独盘面是一个9x9的网格,分为9个3x3的小宫格,每个宫格、每一行、每一列都必须包含数字1到9...
"解数独工具.exe"是这个程序的执行文件,用户可以通过双击运行来启动工具。而"使用说明.txt"则包含了如何操作和使用该工具的详细步骤和提示,包括如何加载数独谜题、如何启用自动解决功能、如何查看解题步骤等。对于...
自动解数独程序,自己写的使用的VB2010,打不开的请先安装.net4.0,源代码在另一个下载里