个人项目·数独
1、Github地址:https://github.com/yefenqin/sudo-
2、解题思路:项目包括 输入与输出(文件读写、命令行),生成不重复终局,解数独三个部分。
(1)输入与输出
文件的读写和使用命令行以前没有接触,通过询问同学和阅读别的同学代码解决这个问题。
(2)生成不重复终局
先确定第一行的九个数,因为第一位是固定的不能改动,改动其他八位数字,第一行全排列有8!=40320种,然后对4-6,7-9行进行交换,再乘3!×3!,结果略大于1e6。
(3)解数独
使用递归,每一列已有的数字标记1,每一行已有的数字标记1,每一块已有的数字标记1。
将未被标记的数字依次填入然后检验即可。
3、代码设计
(1)函数功能
int main(int ,char *) :获取命令行参数,进入不同处理函数
void create(int n):参数为-c时:生成终局存入数组并输出
void solve(char path[]):参数为-s时:标记每行每列每块已有的数字,并进入递归函数fun()
void fun(int x,int y):通过递归解出数独,并且输出
(2)关键函数
生成终局:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 void creat(int n) 2 { 3 ofstream output; 4 output.open("../BIN/sudoku.txt"); 5 int shift[9] = { 0, 3, 6, 1, 4, 7, 5, 8, 2 }; 6 while (n!= 0) 7 { 8 for (int i = 0; i < 6 ; i++) 9 { 10 if (n == 0) continue; 11 if (i) 12 { 13 next_permutation(shift + 3, shift + 6);shift[6] = 5, shift[7] = 8, shift[8] = 2;//调换第4-6列位置 14 } 15 for (int j = 0; j < 6 ; j++) 16 { 17 if (n == 0) continue; 18 if (j) next_permutation(shift + 6, shift + 9);//调换第7-9列位置 19 char row[10] = "912345678"; 20 for (int k = 0; k < 40320 ; k++) 21 { 22 if (n == 0) continue; 23 if (k) next_permutation(row + 1, row + 9);//调换第2-9行位置 24 for (int r = 0; r < 9; r++) 25 { 26 for (int c = 0; c < 9; c++) output << row[(c + shift[r]) % 9] << ' '; 27 output << endl; 28 } 29 output << endl; 30 n--; 31 } 32 } 33 } 34 } 35 output.close(); 36 }
解数独:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 void fun(int x, int y) 2 { 3 ofstream output; 4 output.open("../BIN/sudoku.txt", ios::app); 5 if (flag) return; 6 if (x == 9 && y == 0) { 7 for (int i = 0; i<9; i++) { 8 for (int j = 0; j<9; j++) { 9 output << a[i][j] << " ";//输出解 10 } 11 output << endl; 12 } 13 flag = 1;//输出完成 14 } 15 if (a[x][y] != 0) { 16 if (y == 8) { 17 fun(x + 1, 0); 18 } 19 else 20 fun(x, y + 1); 21 } 22 else 23 for (int i = 1; i <= 9; i++) { 24 if (row[x][i] == 1 || col[y][i] == 1 || g[(x) / 3 * 3 + (y) / 3][i] == 1) 25 continue; 26 a[x][y] = i; 27 row[x][i] = 1; 28 col[y][i] = 1; 29 g[(x) / 3 * 3 + (y) / 3][i] = 1; 30 if (y == 8) 31 fun(x + 1, 0);//一行找完开始找下一行 32 else 33 fun(x, y + 1); 34 row[x][i] = 0; 35 col[y][i] = 0; 36 g[(x) / 3 * 3 + (y) / 3][i] = 0; 37 a[x][y] = 0; 38 } 39 } 40 41 void solve(char path[]) 42 { 43 ifstream input; 44 input.open(path); 45 ofstream output; 46 output.open("../BIN/sudoku.txt"); 47 output.close(); 48 while (!input.eof()) 49 { 50 flag = 0; 51 for (int i = 0; i<9; i++) { 52 for (int j = 0; j<9; j++) { 53 input >> a[i][j]; 54 if (a[i][j] != 0) { 55 row[i][a[i][j]] = 1;//每行已经有了的数字 56 col[j][a[i][j]] = 1;//每列已经有了的数字 57 g[(i) / 3 * 3 + (j) / 3][a[i][j]] = 1;//每块已经有了的数字 58 }//将已有的数字先标记 59 } 60 } 61 fun(0, 0); 62 } 63 input.close(); 64 }
(3)单元测试
命令行参数判定:-c, -s,
运行情况判定:-c 1, -c 1000, -c 1000000, -s 文件路径(其中包含1、1000个用例)
4、运行分析
(1)生成数独终局
(2)解20-40个空格的数独
5.PSP
PSP2.1 |
Personal Software Process Stages |
预估耗时(分钟) |
实际耗时(分钟) |
Planning |
计划 |
40 |
60 |
·Estimate |
·估计这个任务需要多少时间 |
20 |
20 |
Development |
开发 |
1000 |
1000 |
·Analysis |
·需求分析(包括学习新技术) |
200 |
200 |
·Design Spec |
·生成设计文档 |
120 |
90 |
·Design Review |
·设计复审 |
30 |
30 |
·Coding Standard |
·代码规范 |
30 |
30 |
·Design |
·具体设计 |
200 |
200 |
·Coding |
·具体编码 |
480 |
480 |
·Code Review |
·代码复审 |
30 |
30 |
·Test |
·测试 |
30 |
60 |
Reporting |
报告 |
180 |
180 |
·Test Report |
·测试报告 |
40 |
40 |
·Size Measurement |
·计算工作量 |
10 |
10 |
·Postmortem&Process Improvement Plan |
·事后总结并提出过程改进计划 |
90 |
90 |
|
合计 |
2500 |
2520 |