算法基本思想:
1.数据结构,利用short来存每个格子的值。利用低位的9个bit来表示每个格子的值,如果是待确定的格子,则初始化时将最高位的bit置1,低位9个bit全部置1. 如果是已给出或推算出确定的唯一值,只要置上低位9个bit里对应的1个bit。
2.求解思路
(1)遍历每个待确定的格子S,
首先排除S所在9宫其他已确定的值,将那些值对应的bit置0。
第二,排除S所在列的其他已确定的值,将那些值对应的bit置0。
第三,排除S所在行的其他已确定的值,将那些值对应的bit置0。
(2)遍历9个9宫,遍历每个待确定格子,检查该格子的所有可能值,是否有某个可能值只在这个格子里有,而其他8个格子没有的,那么这个格子就是这个值。
(3)只要在(1)(2)中有某个格子得到唯一解,那么整个遍历结束后需要再一次执行(1)(2),直到没有任何格子的值得到唯一解。这时后有2种状态:
1就是全部求得解,打印结果,结束。
2仍然还有待确定的结果,这时就需要猜测值。
找到第一个待确定格子,将其每个可能值列出来,每个可能值拷贝一份数据,压栈,结束。
(4) 如果栈不为空,每次pop出一个拷贝,利用(1)(2)(3)来求解。
附代码如下:
SudokuParser.h
#pragma once
#include <stack>
const short unsureValue = (short) 0x81ff; // first bit and last 9 bits set to 1
const short allUnsureValue = 0x1ff; // last 9 bits set to 1
const short convertValue1 = 0x1;
const short convertValue2 = 0x2;
const short convertValue3 = 0x4;
const short convertValue4 = 0x8;
const short convertValue5 = 0x10;
const short convertValue6 = 0x20;
const short convertValue7 = 0x40;
const short convertValue8 = 0x80;
const short convertValue9 = 0x100;
const short convertData[] = {unsureValue, convertValue1, convertValue2, convertValue3, convertValue4,
convertValue5, convertValue6, convertValue7, convertValue8, convertValue9};
class SudokuData
{
public:
SudokuData() {}
SudokuData(short data[][9]);
SudokuData& operator=(const SudokuData& val);
friend class SudokuParser;
private:
short mData[9][9];
};
class SudokuParser
{
public:
SudokuParser(const SudokuData& data);
~SudokuParser();
// 求解主函数
void parse();
private:
// 返回坐标x,y的方格是否是已经有确定了的唯一值。还是有多种可能,确定的话返回1,否则返回0
int hasConfirm(int x, int y)
{
return !(mSudokuData.mData[x][y] & (1 << 16));
}
// 检查该方格所在的3x3的九格,去掉已经存在的可能值,保留最后剩下的可能值
void single3x3Check(int x, int y);
// 检查该方格所在列的九格,去掉已经存在的可能值,保留最后剩下的可能值
void singleRowCheck(int x, int y);
// 检查该方格所在行的九格,去掉已经存在的可能值,保留最后剩下的可能值
void singleColumnCheck(int x, int y);
// 检查9个 3x3的9宫,遍历每个未确定的格子,检查该格子的所有可能值,是否有某个可能值只在这个格子有,其他8个格子没有的,那么这个格子就是这个值。
int check3x3UnsureCell();
// 找到第一个未确定的格子,将其所有可能值设置上,并压栈。
void guessValue();
// 坐标x,y的格子是未确定的,将其与其所在九宫里的其他未确定格子比较,确定是否有某个值只在这个格子里有,如果有的话,那么这个格子就是这个值。同时返回1,否则返回0
int checkIfOnlyOneValue(int startx, int starty, int x, int y, short value);
// 检查是否此格子的值是只有一个唯一值
int isOnlyOneValue(short value);
// 检查此格子的值是否为0,这表示这格子没有任何可能,一般意味着此数独无解.
int isNoValue(short value);
// 检查是否所有格子都给出了唯一结果。
int isAllCleared();
// 对成员变量mSudokuData开始求解
// return value: -1 means no solution
// 0 means success
// 1 means no solution, but it need to guess value and reparse.
int parseOneData();
// 将内部变量转换成1-9<