代码相关
-
github地址:https://github.com/1449553037/sudoku
-
运行环境: windows10
-
编程语言: C++
-
编程IDE: Visual Studio 2015
执行力 、 泛泛而谈 的理解
-
执行力,我的理解是这样的。第一步,确定一个目标;第二步,计划整个好行动;第三步,执行整个计划;第四步,总结和回顾。执行力就贯穿在这四步,如果有人一件事情按着这四步来,每一步都有实际的行动,并出色的完成。我觉得这个人就是有执行力的。当然很多人做不到的,在做一件事的过程中,懈怠或放弃,最终导致目标没有达成。
-
泛泛而谈,我的理解是。没有明确的观点,没有严谨的逻辑,没有实际案例。
项目需求
-
随机生成N个已解答的数独终盘。
-
输入: 数独棋盘题目个数N(0< N<=1000000)
-
输出: 随机生成N个不重复的数独终盘,并输出到sudoku.txt中
解题思路
随机生成第一行的1~9排列,第2到9行通过回溯法来产生。
对于第2到9行的每一个空格,要从1到9逐个尝试放入,
看同一列、同一行、同一个3×3的小方阵中是否出现过相同的数字,
若没有就尝试放入,然后递归地搜索下一个位置的数字,
若1到9都不行就返回上一个位置尝试下一个数字,直到找到一组解就返回。
遇到的困难及解决方法
- 在做数独的过程中遇到了挺多困难的,比如拿到题目没有思路,找了很多的博客和资料,在编程之美里面找到了很多思路,像回溯法,变换法之类的,还有很多没深究没看懂的解法。在看到回溯法的思路的时候,一直没想明白,尝试一个数的填充,如果违反了三个判断条件,返回后,用下一个数进行尝试,发现走到了死胡同了,这时候要如何回溯,又回溯到哪一步呢。
- 看了很多代码和博客,才想起来递归。
设计实现
- 在main函数中进行命令行参数接收检错、首个数字的生成和输出结果到sudoku.txt。
- 在set_zero函数中将9x9的g格子进行初始化,并完成第一行的数字1~9随机填充。
- 在set_number函数中进行经典回溯法填充余下的2~9行数字。
代码说明
- 健壮性
//参数个数检测
for(int i=0;i<argc;i++) {
count_argv = i;
}
if( count_argv != 2 ) {
cout<<"error: 参数个数要求2个,正确例子“sudoku.exe -c 2”"<<endl;
return 0;
}
//“-c”参数检测
s = argv[1];
if( s.compare("-c") != 0) {
cout<<"error: 参数错误1,正确例子“sudoku.exe -c 2”"<<endl;
return 0;
}
//count参数检测
istringstream stream1;
string string1 = argv[2];
stream1.str(string1);
stream1 >> count;
if ( count == 0 ) {
cout<<"error: 参数错误2,正确例子“sudoku.exe -c 2”"<<endl;
return 0;
}
- 初始化
void start_work(int res)
{
//产生random_shuffle的随机数种子
int temp = rand();
srand ( unsigned ( time (NULL) + temp ) );
//所有格子赋0值
for( int i = 1 ; i <= 9 ; ++i ) {
for( int j = 1 ; j <= 9 ; ++j ) {
set_zero[i][j] = 0 ;
}
}
//第一行赋值1~9
for( int i = 1 ; i <= 9 ; ++i )
set_zero[1][i] = i ;
//将第一行数值随机排列
random_shuffle( &( set_zero[1][1]) , &( set_zero[1][10]) ) ;
//换置学号得到的第一个数字
temp = set_zero[1][1];
for( int i = 1 ; i <= 9 ; ++ i ){
if( set_zero[1][i] == res ){
set_zero[1][i] = temp;
}
}
set_zero[1][1] = res;
//从第二行开始填充数值
set_number( 2 , 1 ) ;
}
- 填充(三个判断)
// is_do 变量用于记录数字k能否放在 ( i , j ) 处
bool is_do = true;
// 检查同一列是否出现过数字k
for( int m = 1 ; m < i ; ++m )
if( set_zero[m][j] == k )
{
is_do = false ;
break ;
}
// 检查同一行是否出现过数字k
if ( is_do )
for( int n = 1 ; n < j ; ++n )
if( set_zero[i][n] == k )
{
is_do = false ;
break;
}
// 检查在3x3的小方格中是否出现了同一个数字
if( is_do )
{
int up1 = ( i/3 ) * 3 + 3 ;
int up2 = ( j/3 ) *3 + 3;
if( i % 3 == 0 )
up1 = i ;
if( j % 3 == 0 )
up2 = j ;
for( int p = up1-2 ; p <= up1 ; ++p )
{
if( is_do == false )
break ;
for( int q = up2-2 ; q <= up2 ; ++q )
if( set_zero[p][q] == k )
{
is_do = false ;
break ;
}
}
}
测试运行
关于执行力与泛泛而谈
PSP
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 60 | 120 |
· Estimate | · 估计这个任务需要多少时间 | 1200 | 4200 |
Development | 开发 | ||
· Analysis | · 需求分析 (包括学习新技术) | 360 | 1200 |
· Design Spec | · 生成设计文档 | 60 | 60 |
· Design Review | · 设计复审 (和同事审核设计文档) | 0 | 0 |
· Coding Standard | · 代码规范 (为目前的开发制定合适的规范) | 60 | 60 |
· Design | 具体设计 | 120 | 600 |
· Coding | 具体编码 | 120 | 1200 |
· Code Review | 代码复审 | 0 | 0 |
· Test | · 测试(自我测试,修改代码,提交修改) | 0 | 0 |
Reporting | 报告 | 60 | 60 |
· Test Report | 测试报告 | 0 | 0 |
· Size Measurement | · 计算工作量 | 60 | 60 |
· Postmortem & Process | Improvement Plan | 事后总结, 并提出过程改进计划 | 60 |
合计 | ** ** | 1200 | 3420 |