上一篇递归求解数独游戏. 本篇给出另一种求解数独游戏方法 // utils.h #ifndef __UTIL_H__ #define __UTIL_H__ const int SHOW_LEN=9; typedef unsigned int uint; #define TRUE 1 #define FALSE 0 #define CONST_CELL 1 #define UNDEF_CELL 0 typedef struct { uint flag:1; uint val:9; }grid; // convert unsigned int to binary string const char * uint2bstring(uint, int length); // convert unsigned int to human readable string const char * uint2hstring(uint); // find how many 1 bits do the parameter has int countOnes(uint value); #endif //utils.cpp //#include "utils.h" #include <string.h> #define MAX_BIT_LEN 32 // convert unsigned int to binary string const char * uint2bstring(uint value, int length) { static char string[MAX_BIT_LEN+1]; int index = 0; memset(string, 0, (MAX_BIT_LEN+1) * sizeof(char)); while(index < length) { string[length - index - 1] = (value & 0x1) + '0'; value >>= 1; ++index; } return string; } // convert unsigned int to human readable string const char * uint2hstring(uint val) { static char string[2*MAX_BIT_LEN+1]; memset(string, 0, (2*MAX_BIT_LEN+1) * sizeof(char)); int index = 0; int count = 0; while(val != 0) { ++count; if((val & 0x1) == 1) { string[index++] = count + '0'; string[index++] = ','; } val >>= 1; } string[--index] = '/0'; return string; } // find how many 1 bits do the parameter has int countOnes(uint value) { int count = 0; while(value != 0) { value &= value - 1; ++count; } return count; } // sudo.cpp #include <stdio.h> #include <stdlib.h> //#include "utils.h" #include <deque> // the sudo is 9x9 grid #define ROW_SIZE 9 #define COL_SIZE 9 #define FMT_BIN 0 #define FMT_HUM 1 grid grids[ROW_SIZE][COL_SIZE]; int initGrid(char* datafile); void printGrid(int fmt=FMT_BIN); int checkUndef(); int iteraterGrid(); int calGrid(int row, int col); int findLeastCell(int *row, int *col); // need one argument, the init file name int main(int argc, char * argv[]) { if (argc < 2) { printf("need to set the data filename!/n"); exit(1); } initGrid(argv[1]); //printGrid(); //printf("undef=%d/n", checkUndef()); int changes = 0; std::deque<grid *> gridQueue; while(TRUE) { do { changes = iteraterGrid(); // printf("=================================*******=================/n"); // printGrid(); // fgetc(stdin); }while(changes > 0); if(changes < 0) {// no solution if(gridQueue.empty()) break; //printf("============= no solution ==========/n"); grid * oldGrid = gridQueue.front(); gridQueue.pop_front(); memcpy(grids, oldGrid, sizeof(grids)); free(oldGrid); } // changes == 0 if(checkUndef() != 0) { int row, col, val; val = findLeastCell(&row, &col); // need recursive solution // find the least 1 in UNDEF_CELL, put into stack and do other //printf("===== split ========/n"); //printf("split (%d, %d) /n", row, col); while((val & (val - 1)) != 0) { grid * newgrid = (grid *)malloc(sizeof(grids)); memcpy(newgrid, grids, sizeof(grids)); newgrid[row * COL_SIZE + col].val = val - (val & (val - 1)); gridQueue.push_front(newgrid); val &= val - 1; } grids[row][col].val = val; } else {// changes == 0 & checkUndef() == 0 // find the solution, translate it to human readable printGrid(FMT_HUM); if(gridQueue.empty()) break; grid * oldGrid = gridQueue.front(); gridQueue.pop_front(); memcpy(grids, oldGrid, sizeof(grids)); free(oldGrid); } } return 0; } int initGrid(char *datafile) { FILE *fpdata; fpdata = fopen(datafile, "rt"); if(fpdata == NULL) { printf("error open datafile!/n"); return FALSE; } for(int i=0; i<ROW_SIZE; i++) { for(int j=0; j<COL_SIZE; ++j) { int value; uint dft_value=0x1FF; fscanf(fpdata, "%d", &value); if(value == 0) { grids[i][j].flag = UNDEF_CELL; grids[i][j].val = dft_value; } else { grids[i][j].flag = CONST_CELL; grids[i][j].val = (1 << (value-1)); } } } return TRUE; } void printGrid(int fmt) { for(int i=0; i<ROW_SIZE; ++i) { for(int j=0; j<COL_SIZE; ++j) { if(fmt == FMT_BIN) printf("%s ", uint2bstring(grids[i][j].val, SHOW_LEN)); else printf("%s ", uint2hstring(grids[i][j].val)); if(j % 3 == 2) printf(" "); } printf("/n"); if(i%3 == 2) printf("/n"); } } int checkUndef() { int count = 0; for(int i=0; i<ROW_SIZE; ++i) { for(int j=0; j<COL_SIZE; ++j) { if(grids[i][j].flag == UNDEF_CELL) ++count; } } return count; } int iteraterGrid() { int changes = 0; for(int i=0; i<ROW_SIZE; ++i) for(int j=0; j<COL_SIZE; ++j) if(grids[i][j].flag == UNDEF_CELL) { grids[i][j].val = calGrid(i, j); if (grids[i][j].val == 0) return -1; // error, no solution else if((grids[i][j].val & (grids[i][j].val - 1)) == 0) { grids[i][j].flag = CONST_CELL; ++changes; } } return changes; } int calGrid(int row, int col) { // check row int i, j; uint val = grids[row][col].val; for(i=0; i<COL_SIZE; ++i) { if(grids[row][i].flag == CONST_CELL) val &= ~grids[row][i].val; } // check column for(j=0; j<COL_SIZE; ++j) { if(grids[j][col].flag == CONST_CELL) val &= ~grids[j][col].val; } // check sub 3x3 grids int rowindex = row / 3; int colindex = col / 3; for(i=rowindex*3; i<(rowindex+1)*3; ++i) for(j=colindex*3; j<(colindex+1)*3; ++j) if(grids[i][j].flag == CONST_CELL) val &= ~grids[i][j].val; return val; } int findLeastCell(int *row, int *col) { int min = 9; for(int i=0; i<ROW_SIZE; ++i) for(int j=0; j<COL_SIZE; ++j) { if(grids[i][j].flag == UNDEF_CELL) { int count = countOnes(grids[i][j].val); if(count < min) { min = count; *row = i; *col = j; } } } return grids[*row][*col].val; }