个人项目——生成数独并解数独【解数独篇】
解数独我并没有想到什么特别好的办法,所以就直接爆搜了23333
基本思路就是一个DFS的过程,用plate[9][9]数组代表整个九宫格,从0~80依次编号,则第x个数在数组中的位置是plate[x/9][x%9],然后只需判断这个位置是不是空,如果是空则放置某个数,若该数合法则递归下一层,x = x+1;若该数不为空则直接递归下一层x = x+1。
注意在退出上一层递归时要将该位置数字“清零”,以免影响下一次放置。
下面附上解数独部分的代码(文件输出后续实现,此处暂用格式输出):
bool check(int x, int m, int n)//检查是否合法 { //行 for (int i = 0; i < 9; i++) if (plate[m][i] == x) return false; //列 for (int i = 0; i < 9; i++) if (plate[i][n] == x) return false; //同一九宫格 int begin_i = m / 3 * 3; int begin_j = n / 3 * 3; for (int i = begin_i; i < begin_i + 3; i++) for (int j = begin_j; j < begin_j + 3; j++) if (plate[i][j] == x) return false; return true; } void solve(int count)//递归解数独 { if (flag) return; if (count == 81) { flag = true; for (int i = 0; i < 9; i++) { printf("%d", plate[i][0]); for (int j = 1; j < 9; j++) printf(" %d", plate[i][j]); printf("\n"); } return; } int m = count / 9; int n = count % 9; if (plate[m][n] == 0) { for(int i = 1; i <= 9; i ++) if (check(i, m, n)) { plate[m][n] = i; solve(count + 1); } plate[m][n] = 0; } else solve(count + 1); }
关于解数独效率的问题,如果项目大致写完还有剩余时间我会继续优化。
4.11更新 【改为文件输出】
bool check(int x, int m, int n) { for (int i = 0; i < 9; i++) if (plate[m][i] == x) return false; for (int i = 0; i < 9; i++) if (plate[i][n] == x) return false; int begin_i = m / 3 * 3; int begin_j = n / 3 * 3; for (int i = begin_i; i < begin_i + 3; i++) for (int j = begin_j; j < begin_j + 3; j++) if (plate[i][j] == x) return false; return true; } void solve(int count) { if (flag) return; if (count == 81) { flag = true; for (int i = 0; i < 9; i++) { fputc(plate[i][0]+ '0', output_solve); for (int j = 1; j < 9; j++) { fputc(' ', output_solve); fputc(plate[i][j]+ '0', output_solve); } fputc('\n', output_solve); } fputc('\n', output_solve); return; } int m = count / 9; int n = count % 9; if (plate[m][n] == 0) { for(int i = 1; i <= 9; i ++) if (check(i, m, n)) { plate[m][n] = i; solve(count + 1); } plate[m][n] = 0; } else solve(count + 1); }