软件工程实践2017第二次作业
Github:sudoku
项目相关要求
利用程序随机构造出N个已解答的数独棋盘 。
输入
数独棋盘题目个数N(N在0和1000000之间)
输出
随机生成N个不重复的已解答完毕的数独棋盘,并输出到sudoku.txt中。在生成数独矩阵时,左上角的第一个数为:(学号后两位相加)% 9 + 1。
思路与代码
一暑假没碰过代码的我,在暑假结束前一周看到了这个作业题目,脑子里想起来的就是大一的时候敲得八皇后和马遍历的题目,比较类似,都是关于递归回溯的算法。大致思路就是给每个格子试不同的数,找到符合条件的填下,如果不可以的就回到前一个,换一个数再试试,不行再回溯,于是有了下面的代码:
int count=0;//统计输出了多少数独
void sudoku(int i,int j)
{
for(int x=1;x<=9;x++)//给每个格子都试9个数
{
if(check(i,j,x)==1)//如果可以
{
board[i][j]=x;//就赋值
if(i==8&&j==8)//如果填满了,就输出
{
print();
count++;
if(count>=N) exit(-1);
return;//输出还没到N个,就继续返回试其他数
}
if(j==8)//如果当前位置是某一行最后一个,就跳到下一行第一个
{
sudoku(i+1,0);
}
else//不然就跳到下一个
{
sudoku(i,j+1);
}
}
}
board[i][j]=0;
return ;//这个格子没有一个数符合,就返回上一个格子
}
下面是判断这个格子是否可以这个数的check函数:
int check(int row,int col,int num)//判断是否能放
{
for(int i=0;i<9;i++)//判断列有没相同的
{
if(board[i][col]==num)return 0;
}
for(int j=0;j<9;j++)//判断行有没相同的
{
if(board[row][j]==num)return 0;
}
int x=row/3,y=col/3;
x=3*x;
y=3*y;
for(int i=0;i<3;i++)//检查小九宫格
{
for(int j=0;j<3;j++)
{
if(board[x+i][y+j]==num)return 0;
}
}
return 1;
}
生成100W个数独大概要52秒左右
生成的结果输出到sudoku.txt
性能分析
用VS自带的性能分析器进行分析,测试的生成的数独为10W个:
PSP
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | ||
· Estimate | · 估计这个任务需要多少时间 | 800 | 1000 |
Development | 开发 | ||
· Analysis | · 需求分析 (包括学习新技术) | 120 | 130 |
· Design Spec | · 生成设计文档 | 0 | 0 |
· Design Review | · 设计复审 (和同事审核设计文档) | 0 | 0 |
· Coding Standard | · 代码规范 (为目前的开发制定合适的规范) | 60 | 60 |
· Design | · 具体设计 | 90 | 120 |
· Coding | · 具体编码 | 270 | 330 |
· Code Review | · 代码复审 | 60 | 60 |
· Test | · 测试(自我测试,修改代码,提交修改) | 90 | 90 |
Reporting | 报告 | ||
· Test Report | · 测试报告 | 120 | 110 |
· Size Measurement | · 计算工作量 | 30 | 30 |
· Postmortem & Process Improvement Plan | · 事后总结, 并提出过程改进计划 | 60 | 60 |
合计 | 900 | 1050 |
反思与总结
这次代码虽然思路简单,但是递归实现起来理解的意思确实很复杂,因为好久没敲这类题,已经忘记了当时如何理解递归。经过一番痛苦挣扎(把之前八皇后和马遍历的代码翻出来温习了一下),总算有点想明白,递归就是层层递归,就像一颗树一样,从根节点递归到子节点,子节点行不通,return会根节点从旁路走。其实我还想了一种方法(其实是网上看到的),就是把九宫格分成九个独立的宫,因为每个宫都会有1-9九个数字,所以就按数字来放,比如先把1排进每个宫,接着放2,以此类推,而且在放头尾两个数的时候完全不用回溯,我觉得应该会减少代码运行复杂度,我也尝试的敲了下,奈何学艺不精没有成功,于是就选了这种普通的方法。这很反映了我现在的代码能力很弱,需要加强咯。