1、github地址:https://github.com/kinglc/sudoku1943
2、解题思路:项目包括 输入与输出(文件读写、命令行),生成不重复终局,解数独三个部分。
(1)输入与输出
文件读写和命令行虽然都不熟,但稍微百度就完全可以解决。
(2)生成不重复终局
先随便写了一个数独终局
1 2 3 4 5 6 7 8 9
4 5 6 7 8 9 1 2 3
7 8 9 1 2 3 4 5 6
2 3 4 5 6 7 8 9 1
5 6 7 8 9 1 2 3 4
8 9 1 2 3 4 5 6 7
3 4 5 6 7 8 9 1 2
6 7 8 9 1 2 3 4 5
9 1 2 3 4 5 6 7 8
只需要生成一定数量的数独终局从简单的入手就好,上图第一行是随手写,后8行都可以看做根据第一行左移得到,第一行全排列有8!=40320种,然后交换2-3(因为数据只要求1e6,可以不 考虑),4-6,7-9行,再乘3!×3!,结果略大于1e6。
(3)解数独
本来试着看了一下dancing links算法,但十字链表似乎好麻烦的样子,于是老老实实用dfs暴力写完了。
3、代码设计
(1)函数功能
int main(int ,char *) :获取命令行参数,进入不同处理函数
void createFinal():参数为-c时:生成终局存入数组,并调用output(int,int)函数
void workout(int):参数为-s时:通过深搜得出终局,用check(int,int)函数判断,并调用output(int,int)函数
bool check(int,int):判断在该处填的数字是否合理
void output(int,int):根据参数所代表的输出顺序输出终局
(2)关键函数
生成终局:
void createFinal() { int tmp[9] = { 8,9,1,2,3,4,5,6,7 };//tmp表示第一行数字 int i, j, k, moveleft[8] = { 3,6,1,4,7,2,5,8 }; //moveleft表示2-9行在第1行基础上整体左移位数 for (i = 0; i < 40320; i++) //8!=40320 { memcpy(numBoard[0], tmp, sizeof(tmp)); //将第1行左移生成2-9行 for (j = 0; j < 8; j++) for (k = 0; k < 9; k++) numBoard[j + 1][k] = numBoard[0][(k + moveleft[j]) % 9];//初始图完成 //调换4-6,7-9行 for (j = 0; j < 6; j++) for (k = 0; k < 6; k++) { output(j, k); if (!--testnum) return; } next_permutation(tmp + 1, tmp + 9);//重置第一行 } return; }