diff --git a/Sudoku.cpp b/Sudoku.cpp index e758206..dfaf879 100644 --- a/Sudoku.cpp +++ b/Sudoku.cpp @@ -1,315 +1,313 @@ -#include -#include -#include -using namespace std; -ifstream File_Input; -ofstream File_Output; - -struct Sudoku_Class{ //一个宫格的内容 - unsigned char Data; //数字1~9,0表示未完成 - bool May[9]; //假设数 -}; -struct Try_Point_Class{ //假设链上的节点 - unsigned char Block_Num; //被假设的宫格编号 - unsigned char Point_Num; //当前正在被假设的Item编号 - vector Item; //节点中的所有假设数 -}; - -struct Sudoku_Class Base[81]; //全部81个宫格 -struct Sudoku_Class Backup[81]; //进行假设的时候暂存使用 -unsigned char Addr_Kind[3][9][9]; //行列宫对应的位置表 -unsigned char Addr_Block[81][3]; //宫格所在行列宫的编号 -vector Try; //假设链 -struct Try_Point_Class Empty_Point; //空的假设节点 -unsigned char Mode; - -void Init(); -void Analyse(); -void Engine(); -bool Check_Compete(); -bool Check_Error(); -void Create_New_Point(); -void Solve_Output(); -bool Try_Next(); -void Data_Input(); -unsigned int Calculate(); -unsigned char Next_Empty_Block(unsigned char Start); -void Init_Point(unsigned char Block_Num,unsigned char Point_Num); - -int main(){ - unsigned int Solve_Num,Dat; - Init(); - cout<<"Welcome to Sudoku-Calculator!"<>Dat; - if((Dat>=1)&&(Dat<=3)){Mode=Dat;}else{goto Restart;} - cout<<"The mode is "<>Dat; - if(Dat==43){ // ‘+’ - if(Num<=79){Num++;} - goto Next; - } - else if(Dat==45){ // '-' - if(Num>=1){Num--;} - goto Next; - } - else if(Dat==42){ // '*' - if(Num<=71){Num=Num+9;} - goto Next; - } - else if(Dat==47){ // '/' - if(Num>=9){Num=Num-9;} - goto Next; - } - else if(Dat==61){} // '=' - else if((Dat>=48)&&(Dat<=57)){ - Base[Num].Data=int(Dat-48); - if(Num<=79){Num++;} - goto Next; - } - else{goto Next;} -} -void Solve_Output(){ - unsigned char i; - char Data[82]; - if(Mode==2){return;} - for(i=0;i<=80;i++){Data[i]=Base[i].Data+48;} - Data[81]=0; - if(Mode==0){ - cout<=(Try[Try.size()-1].Item.size()-1))){ - if(Try.size()==1){return false;} - Try.resize(Try.size()-1); - } - Try[Try.size()-1].Point_Num++; //假设链末节点指向下一个Item - for(i=0;i<=80;i++){ //将备份数据重新装载 - Base[i]=Backup[i]; - } - return true; //成功 -} -void Create_New_Point(){ //创建新的假设链节点 - Try.push_back(Empty_Point); - if(Try.size()==1){ //若为根节点 - Init_Point(Next_Empty_Block(0),0); //从第一格开始搜索未完成宫格 - } - else{ //若不是根节点 - Init_Point(Next_Empty_Block(Try[Try.size()-2].Block_Num+1),Try.size()-1); //从上一节点指向的宫格开始搜索未完成宫格 - } -} -void Init_Point(unsigned char Block_Num,unsigned char Point_Num){ //初始化假设链节点 Block_Num->被假设宫格的编号 Point_Num->节点的编号 - unsigned char i; - Try[Point_Num].Block_Num=Block_Num; - for(i=0;i<=8;i++){ - if(Base[Try[Point_Num].Block_Num].May[i]==true){ //遍历目标宫格的所有假设数并加入到该节点的Item中 - Try[Point_Num].Item.push_back(i+1); - } - } - Try[Point_Num].Point_Num=0; //指向Item中的第一个假设数 -} -unsigned char Next_Empty_Block(unsigned char Start){ //找到下一个未确定答案的宫格并返回其编号 - unsigned char i; - for(i=Start;i<=80;i++){ - if(Base[i].Data==0){return i;} - } - return 0; //没有未确定宫格 -} -bool Check_Error(){ //检查数独是否存在错误 - unsigned char kind,num,add,item; - for(kind=0;kind<=2;kind++){ //分别扫描行列宫 - for(num=0;num<=8;num++){ - for(item=1;item<=9;item++){ - add=0; - for(unsigned char k=0;k<=8;k++){ - if(Base[Addr_Kind[kind][num][k]].Data==item){add++;} - } - if(add>=2){return true;} //若一组行列宫中存在两个相同的数 -> 错误退出 - } - } - } - for(num=0;num<=80;num++){ //扫描全部宫格 - if(Base[num].Data==0){ //若未完成 - add=0; - for(unsigned char k=0;k<=8;k++){ //遍历其所有假设数 - if(Base[num].May[k]==true){add++;} - } - if(add==0){return true;} //没有可能的数 -> 错误退出 - } - } - return false; //暂时未发现错误 -} -bool Check_Compete(){ //判断数独是否完成 - unsigned char i; - for(i=0;i<=80;i++){ - if(Base[i].Data==0){return false;} - } - return true; -} -void Engine(){ //使用排除法 - unsigned char kind,num,item,add,dat; - bool Could_Solve; - Again:; - Analyse(); //每次排除前应先消去假设数 - Could_Solve=false; - for(kind=0;kind<=2;kind++){ //分别扫描行列宫 - for(num=0;num<=8;num++){ - for(item=0;item<=8;item++){ - add=0; - for(unsigned char k=0;k<=8;k++){ - if((Base[Addr_Kind[kind][num][k]].Data==0)&&(Base[Addr_Kind[kind][num][k]].May[item]==true)){add++;dat=k;} //记录一组行列宫中的可能数 - } - if(add==1){Base[Addr_Kind[kind][num][dat]].Data=item+1;Could_Solve=true;} //若仅有唯一可能数,则该宫格答案确定 - } - } - if(Could_Solve==true){goto Again;} //一直循环直到没有排除对象 - } -} -void Analyse(){ //消去假设数 - unsigned char num,kind,item; - for(num=0;num<=80;num++){ //遍历所有宫格 - if(Base[num].Data!=0){ //若该宫格已完成 - for(kind=0;kind<=2;kind++){ //分别对行列宫操作 - for(item=0;item<=8;item++){ - Base[Addr_Kind[kind][Addr_Block[num][kind]][item]].May[Base[num].Data-1]=false; //消去同行同列同宫的假设数 - } - } - } - } -} -void Init(){ //初始化容器 - unsigned char i,j,x,y; - for(i=0;i<=8;i++){ //初始化行与列的位置表 - for(j=0;j<=8;j++){ - Addr_Kind[0][i][j]=i*9+j; - Addr_Kind[1][i][j]=j*9+i; - } - } - for(x=0;x<=2;x++){ //初始化九宫格的位置表 - for(y=0;y<=2;y++){ - for(i=0;i<=2;i++){ - for(j=0;j<=2;j++){ - Addr_Kind[2][y*3+x][j*3+i]=(y*3+j)*9+(x*3+i); - } - } - } - } - for(i=0;i<=2;i++){ //初始化宫格所在行列宫的编号 - for(x=0;x<=8;x++){ - for(y=0;y<=8;y++){ - Addr_Block[Addr_Kind[i][x][y]][i]=x; - } - } - } - for(i=0;i<=80;i++){ //清空所有假设数 - for(j=0;j<=8;j++){ - Base[i].May[j]=true; - } - } - for(i=0;i<=80;i++){ //清空所有数字 - Base[i].Data=0; - } -} +#include +#include +#include +using namespace std; +ifstream File_Input; +ofstream File_Output; + +struct Sudoku_Data { //һ + unsigned char Data; //1~9 0ʾδ + bool May[9]; // +}; +struct Try_Point { //ϵĽڵ + unsigned char Block_num; //Ĺ + unsigned char Point_num; //ǰڱitem + vector item; //ڵем +}; + +struct Sudoku_Data Base[81]; //ȫ81 +struct Sudoku_Data Backup[81]; //мʱݴʹ +unsigned char Addr_Kind[3][9][9]; //йӦλñ +unsigned char Addr_Block[81][3]; //йı +vector Try; // +struct Try_Point Empty_Point; //յļڵ +bool display; //Solve_OutputʱǷ + +void Init(); +void Analyse(); +void Engine(); +bool Check_Compete(); +bool Check_Error(); +void Create_New_Point(); +void Solve_Output(); +bool Try_Next(); +void Data_Input(); +unsigned int Calculate(); +unsigned char Next_Empty_Block(unsigned char Start); +void Init_Point(unsigned char Block_num,unsigned char Point_num); + +int main() { + unsigned int Solve_num, dat; + Init(); + cout<<"Welcome to Sudoku-Calculator by Dnomd343"<>dat; + cin.get(); + if (dat == 1) { + display=false; + } else if (dat == 2) { + display=true; + } else { + goto Reinput; + } + cout<<"Please Wait..."<>dat; + if (dat == 43) { // '+' + if (num <= 79) {num++;} + goto Next; + } else if (dat == 45) { // '-' + if (num >= 1) {num--;} + goto Next; + } else if (dat == 42) { // '*' + if (num <= 71) {num = num + 9;} + goto Next; + } else if (dat == 47) { // '/' + if (num >= 9) {num = num - 9;} + goto Next; + } else if (dat == 61) {// '=' + } else if ((dat >= 48) && (dat <= 57)) { // 0~9 + Base[num].Data = int(dat - 48); + if (num <= 79) {num++;} + goto Next; + } else { // + goto Next; + } +} +void Solve_Output() { //ģʽʾ + if (display == true) { //ȷǷģʽ + cout<= (Try[Try.size()-1].item.size()-1)) { + if (Try.size() == 1) {return false;} + Try.resize(Try.size()-1); + } + Try[Try.size()-1].Point_num++; //ĩڵָһitem + for (i = 0; i < 81; i++) {Base[i] = Backup[i];} //װر + return true; +} +void Create_New_Point() { + Try.push_back(Empty_Point); + if (Try.size() == 1) { //Ϊڵ + Init_Point(Next_Empty_Block(0),0); //ӵһʼδɹ + } else { //Ǹڵ + Init_Point(Next_Empty_Block(Try[Try.size()-2].Block_num+1),Try.size()-1); //һڵָĹʼδɹ + } +} +void Init_Point(unsigned char Block_num,unsigned char Point_num) { //ʼڵ Block_num->蹬ı Point_num->ڵı + unsigned char i; + Try[Point_num].Block_num = Block_num; + for (i = 0; i < 9; i++) { + if (Base[Try[Point_num].Block_num].May[i] == true) { //Ŀ깬м뵽ýڵitem + Try[Point_num].item.push_back(i + 1); + } + } + Try[Point_num].Point_num = 0; //ָitemеĵһ +} +unsigned char Next_Empty_Block(unsigned char Start) { //ҵһδȷ𰸵Ĺ񲢷 + unsigned char i; + for (i = Start; i < 81; i++) { + if (Base[i].Data == 0) {return i;} + } + return 0; //ûδȷ +} +bool Check_Error() { //Ƿڴ + unsigned char kind, num, add, item; + for (kind = 0; kind < 3; kind++) { //ֱɨй + for (num = 0; num < 9; num++) { + for (item = 1; item <= 9; item++) { + add = 0; + for (unsigned char k = 0; k < 9; k++) { + if (Base[Addr_Kind[kind][num][k]].Data == item) {add++;} + } + if (add >= 2) {return true;} //һйдͬ -> ˳ + } + } + } + for (num = 0; num < 81; num++) { //ɨȫ + if (Base[num].Data == 0) { //δ + add = 0; + for (unsigned char k = 0; k < 9; k++) { //м + if (Base[num].May[k] == true) {add++;} + } + if (add == 0) {return true;} //ûпܵ -> ˳ + } + } + return false; //ʱδִ +} +bool Check_Compete() { //жǷ + unsigned char i; + for (i = 0; i < 81; i++) { + if (Base[i].Data == 0) {return false;} + } + return true; +} +void Engine() { //ʹųȥܵ + unsigned char kind, num, item, add, dat; + bool Could_Solve; +Again:; + Analyse(); //ÿųǰӦȥ + Could_Solve = false; + for (kind = 0; kind < 3; kind++) { //ֱɨй + for (num = 0; num < 9; num++) { + for (item = 0; item < 9; item++) { + add = 0; + for(unsigned char k = 0; k < 9; k++) { //¼һйеĿ + if ((Base[Addr_Kind[kind][num][k]].Data == 0) && (Base[Addr_Kind[kind][num][k]].May[item] == true)) { + add++; + dat = k; + } + } + if (add == 1) { //Ψһùȷ + Base[Addr_Kind[kind][num][dat]].Data = item + 1; + Could_Solve = true; + } + } + } + if (Could_Solve == true) {goto Again;} //һֱѭֱûų + } +} +void Analyse() { //ȥ + unsigned char num, kind, item; + for (num = 0; num < 81; num++) { //й + if (Base[num].Data != 0) { //ù + for (kind = 0; kind < 3; kind++) { //ֱɨй + for (item = 0; item < 9; item++) { + Base[Addr_Kind[kind][Addr_Block[num][kind]][item]].May[Base[num].Data - 1] = false; //ȥͬͬͬļ + } + } + } + } +} +void Init() { //ʼ + unsigned char i, j, x, y; + for (i = 0; i < 9; i++) { //ʼеλñ + for (j = 0; j < 9; j++) { + Addr_Kind[0][i][j] = i * 9 + j; + Addr_Kind[1][i][j] = j * 9 + i; + } + } + for (x = 0; x < 3; x++) { //ʼŹλñ + for (y = 0; y < 3; y++) { + for (i = 0; i < 3; i++) { + for (j = 0; j < 3; j++) { + Addr_Kind[2][y*3 + x][j*3 + i] = (y*3 + j) * 9 + (x*3 + i); + } + } + } + } + for (i = 0; i < 3; i++) { //ʼйı + for (x = 0; x < 9; x++) { + for (y = 0; y < 9; y++) { + Addr_Block[Addr_Kind[i][x][y]][i] = x; + } + } + } + for (i = 0; i < 81; i++) { //м + for (j = 0; j < 9; j++) { + Base[i].May[j] = true; + } + } + for (i = 0; i < 81; i++) {Base[i].Data = 0;} // +}