软件工程实践2019第三次作业
软件工程实践2019第三次作业
Gethub项目地址:
https://github.com/liuxinyao0722
PSP表格:
PSP2.1 | Personal Software Process Stages | 预估耗时(小时) | 实际耗时(小时) |
---|---|---|---|
Planning | 计划 | 1h | 1h |
Estimate | 估计这个任务需要多少时间 | 21h | 20h |
Development | 开发 | 3h | 3h |
Analysis | 需求分析 (包括学习新技术) | 2h | 2.5h |
Design Spec | 生成设计文档 | 2h | 1.5h |
Design Review | 设计复审 | 0.5h | 0.5h |
Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 2h | 2h |
Design | 具体设计 | 3h | 2.5h |
Coding | 具体编码 | 1h | 1h |
Code Review | 代码复审 | 1h | 0.5h |
Test | 测试(自我测试,修改代码,提交修改) | 3h | 2.5h |
Reporting | 报告 | 1h | 1h |
Test Repor | 测试报告 | 0.5h | 0.5h |
Size Measurement | 计算工作量 | 1h | 1h |
Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 1h | 1h |
合计 | 22h | 20.5h |
解题思路
一开始在看到题目的时候,因为之前玩过数独,大家基本思路都一样,填入数独初步的思路是设计2~3个函数,一两个函数判断行或列数字是否重复,一个函数判断宫中的数字是否重复(4,6,8,9需要判断宫的数字),然后如果重复了怎么填入数字,一开始没有思路,借鉴了几篇博客后,想起了回溯遍历DFS的方法,所以思路大概是输入文件 填数 判断重复 回溯 输出文件这几部分。其中,填数和判断重复反复回溯判断。
函数:数独清空重置
void memset(){ //初始化数独数组
for(i=0;i<9;i++)
for(j=0;j<9;j++){
sudu[i][j]=0;
}
}
行列重复判断函数
bool hanglie(int x, int w)//验证行与列,宫格为4 6 8 9的时候需要判断宫
{
int row= x/m;
int column=x%m;
for (int i=0;i<m;i++)//行
{
if (sudu[row][i]== w)
{ return 0; }
}
for (int i=0;i<m;i++)//列
{
if (sudu[i][column] == w)
{return 0;}
}
if (m==4)//4宫格
{
if (gong(x,2,2,w)) {return 1;}
else{return 0; }
}
else if (m==6)//6宫格
{
if (gong(x,2,3,w)) { return 1;}
else {return 0;}
}
else if (m==8)//8宫格
{
if (gong(x,4,2,w)) {return 1;}
else {return 0;}
}
else if (m==9)//9宫格
{
if (gong(x,3,3,w)) {return 1;}
else {return 0;}
}
return 1;
}
宫的重复判断
bool gong(int x,int row,int column,int w)//判断宫
{ int a,b;
a=x/m;b=x%m;
a=a/row*row;//行
b=b/column*column;//列
for (int i=a;i<a+row;i++)
{ for (int j=b;j<b+column;j++)
{ if (sudu[i][j] == w)
{ return 0; }
}
}
return 1;
}
DFS函数
void DFS(int x)//回溯遍历
{ int row,column;//定义行和列
if (finish)//若已完成 直接返回
{return;}
if (x==m*m)//已经找完 输出返回
{ output();
finish = 1;
return;
}
row= x/m;//行
column=x%m;//列
if (!sudu[row][column])//位置为空则填入数字
{ for (int i=1;i<=m;i++)
{ if (hanglie(x,i))
{ sudu[row][column] = i;
DFS(x+1);
sudu[row][column] = 0;//回溯
}
}
}
else//有数字则跳过
{ DFS(x+1);}
}
输出函数
void output()//输出
{ for (i=0;i<m;i++)
{for (j=0;j<m;j++)
{ fprintf(fpout,"%d",sudu[i][j]);//打印到输出文件
if (j<m-1)//非行末都要加空格
{
fprintf(fpout, " ");
}
}
fprintf(fpout, "\n");//每行结束换行
}
}
主函数
int main(int argc, char *argv[])
{ m=atoi(argv[2]);//宫格数
n=atoi(argv[4]);//盘数
char *inname = argv[6];//输入文件名
char *outname = argv[8];//输出文件名
fpin = fopen(inname, "r");//打开输入文件
if (fpin==NULL) {
return -1;}
fpout = fopen(outname,"w");//打开输出文件
if (fpout==NULL) {
return -1;}
fclose(fpout);//关闭输出文件
while(n--)//当盘数非0循环
{ finish = 0;
memset();//初始化 置零
for(int i=0;i<m;i++)
{ for(int j=0;j<m;j++)
{fscanf(fpin,"%d",&sudu[i][j]);}//文件读入
}
fpout = fopen(outname,"a");//打开输出文件
DFS(0); //填入数字
if (n>0)//盘数非0时,打印到输出文件
{fprintf(fpout,"\n");}
fclose(fpout);//关闭输出文件
}
fclose(fpin);//关闭输入文件
return 0;
}
示例测试:
3宫格
4宫格
5宫格
6宫格
7宫格
8宫格
9宫格
性能测试