生成数独终局和求解数独
Github地址:https://github.com/BIT1120161913/sudoku
PSP | Personal Software Process Stages |
ړ预估耗时(分钟) | 实际耗时(分钟) |
Planning | 计划 | 120 | 60 |
· Estimate | ·估计任务需要多长时间 | ||
Development | 开发 | ||
· Analysis | 需求分析(包括学习新技术) | 240 | 300 |
· Design Spec | 生成设计文档 | 120 | |
· Design Review | 设计复审 | 60 | 60 |
Coding Standard | 代码规范 | 60 | 90 |
Design | 具体设计 | 240 | 300 |
Coding | 具体编码 | 1800 | 2000 |
Code Review | 代码复审 | 240 | 360 |
Test | 测试 | 240 | 240 |
Reporting | 报告 | 30 | |
Test Report | 测试报告 | 90 | |
Size Measurement | 计算工作量 | ||
Postmortem & Process Improvement Plan | 总结并题出改进计划 | 120 | 30 |
合计 | 3240 | 3250 |
解题思路:
我之前从未玩过数独,看了要求之后首先百度什么是数独,又查了下如何生成终局,主要思路是通过对一个数独终局进行行变换和列变换,可以生成新的数独终局。为了生成足够多的数独终局,必须有足够多的初始数独终局。首先第一行第一个数是固定的,然后第一行后8个数由9个数中剩余的数随机组成,可以生成第一行后8个数的全排列,每生成一行就会得到一个数独终局,然后对该终局进行行变换,生成更多的终局。
我不会通过命令行来运行程序,查了查命令行的资料,发现命令行中的指令会传到main函数的两个形式参数argc,argv[][]中,可以利用argv[1]判断是生成终局还是解数独,利用argv[2]得知生成数独数量和待解数独文件。
学习C语言的时候,没有考文件的相关知识,所以我现在对文件一无所知,上网现学如何读取文件内容以及写入。用到的文件的知识较少,我只用到了fopen(),fclose(),fputc(),fgets()这几个,比较简单,但学习使用他们花了大量时间。
Github完全不会用,第一次注册时根据英文指导建立了一个仓库,当时只知道傻乎乎的看英文,没有上网搜搜看有没有汉语说明,花了几个小时按英语说明走了一遍,仍然非常生疏。
设计实现:
主函数包含两个函数:void Permutation(int begin)和void input()。
void Permutation(int begin)嵌套void sudoku();void sudoku()嵌套void swap(int i, int begin),void swap_a(int x,int y)和 void put();
void input()嵌套void dfs(int row, int col)和void put()。
void Permutation(int begin)回溯生成seed数组的一个全排列数后,将seed数组所有数和a[0][0]合并为a数组第一行,然后调用void sudoku(),void sudoku()每生成一个数独终局时,调用void put()写入文件,设置一个全局变量count控制生成终局数量。
void input()从文件读入待求解数独,每读入一个终局,调用void dfs(int row, int col)回溯解出数独,再调用void put()写入文件,最后循环读入另一个数独终局。
关键代码:
1 for(i = 0; i < 6; i++){ 2 switch(i) 3 { 4 case 0: swap_a(0,0);break; 5 case 1: swap_a(4,5);break; 6 case 2: swap_a(3,4);break; 7 case 3: swap_a(3,4);swap_a(4,5);break; 8 case 4: swap_a(3,5);swap_a(4,5);break; 9 case 5: swap_a(3,5);break; 10 } 11 12 for(j = 0; j < 6; j++){ 13 switch(j) 14 { 15 case 0: swap_a(0,0);break; 16 case 1: swap_a(7,8);break; 17 case 2: swap_a(6,7);break; 18 case 3: swap_a(6,7);swap_a(7,8);break; 19 case 4: swap_a(6,8);swap_a(7,8);break; 20 case 5: swap_a(6,8);break; 21 } 22 if(count < sum){ 23 put(); 24 count ++; 25 }else break; 26 switch(j) 27 { 28 case 0: swap_a(0,0);break; 29 case 1: swap_a(7,8);break; 30 case 2: swap_a(6,7);break; 31 case 3: swap_a(7,8);swap_a(6,7);break; 32 case 4: swap_a(7,8);swap_a(6,8);break; 33 case 5: swap_a(6,8);break; 34 } 35 } 36 37 switch(i) 38 { 39 case 0: swap_a(0,0);break; 40 case 1: swap_a(4,5);break; 41 case 2: swap_a(3,4);break; 42 case 3: swap_a(4,5);swap_a(3,4);break; 43 case 4: swap_a(4,5);swap_a(3,5);break; 44 case 5: swap_a(3,5);break; 45 } 46 if(count >= sum) 47 break; 48 }
生成一个数独终局后,3,4,5行之间互相交换,6,7,8行之间互相交换,生成更多数独终局。