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