软件工程实践2019第三次作业
github地址
https://github.com/bamboooooos/031702416
PSP表格
Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|
计划 | 20 | 10 |
估计这个任务需要多少时间 | 10 | 2 |
开发 | 180 | 200 |
需求分析 (包括学习新技术) | 60 | 120 |
生成设计文档 | 60 | 60 |
设计复审 | 10 | 10 |
代码规范 (为目前的开发制定合适的规范) | 10 | 10 |
具体设计 | 40 | 30 |
具体编码 | 120 | 180 |
代码复审 | 30 | 20 |
测试(自我测试,修改代码,提交修改) | 180 | 200 |
报告 | 60 | 30 |
测试报告 | 60 | 30 |
计算工作量 | 20 | 20 |
事后总结, 并提出过程改进计划 | 40 | 30 |
合计 | 900 | 952 |
解题思路
一开始看到需求没有什么太明确的思路,想了一会只想到一个一个填然后看有没有冲突;
睡午觉前上知乎百度找了下别人的算法,发现思路都差不多,睡了一觉起来大概有了一整个程序的思路;
文件输入输出流读写数独题,每一个题放在一个二维数组然后存放在ArrayList里面;
把题目一个一个取出来解题,解题就从[0][0]到最后一个有效的元素,先判断是否需要改,从1到9替换,进行行列宫测试,无冲突就进行下一个元素的判断,1到9都冲突就退回到上一个再+1;
流程图
代码
处理参数部分
参数一般为-m (m) -n (n) -i (input) -o (output)
简便处理直接取String数组args第1,3,5,7个元素
int rank=Integer.valueOf(args[1]).intValue();
int problem=Integer.valueOf(args[3]).intValue();
String filein=args[5];
String fileout=args[7];
输入部分
用文件流读取并将每个题放到ArrayList里
ArrayList<int[][]> problems=new ArrayList<>();
ArrayList<int[][]> results=new ArrayList<>();
try {//输入问题
File file=new File(filein);
BufferedReader bw=new BufferedReader(new FileReader(file));
for(int times=0;times<problem;times++) {
int[][] prob=new int[9][9];
for(int i=0;i<rank;i++) {
String toint=bw.readLine();
String str = toint.replaceAll(" ","");
for(int j=0;j<rank;j++) {
prob[i][j]=Integer.valueOf(str.charAt(j)).intValue()-48;
}
}
bw.readLine();
problems.add(prob);
}
bw.close();
}catch(Exception e) {
e.printStackTrace();
}
解题部分
将每一个题用solve方法解题后存放到ArrayList等待写到文件中
main里面的方法
for(int i=0;i<problem;i++) {//解决问题
results.add(solve(problems.get(i),rank));
}
solve方法逻辑
将每个题(二维数组)传到solve方法中,对每个需要填的位置用test方法测试是否冲突,无冲突则测试下一个,没有无冲突的数则回到上一个
public static int[][] solve(int [][] problem,int rank){
int [][] result=problem;
int[] numX=new int[81];
int[] numY=new int[81];
int[] numNow=new int[81];
int tosolve=0;
numX[0]=0;
numY[0]=0;
numNow[0]=0;
for(int i=0;i<rank;i++) {//存储需要更改的位置
for(int j=0;j<rank;j++) {
if(result[i][j]==0) {
numX[tosolve]=i;
numY[tosolve]=j;
tosolve++;
}
}
}
int count=0;
int x=0,y=0;
for(;count<tosolve;) {
x=numX[count];
y=numY[count];
int i=numNow[count]+1;
for(;i<=rank;i++) {
result[x][y]=i;
if(test(result,x,y,rank)) {//替换成功
numNow[count]=i;
count++;
for(int clear=count;clear<tosolve;clear++) {
numNow[clear]=0;
}
//log(result);
break;
}
}
if(i==rank+1) {
for(int clear=count;clear<tosolve;clear++) {//错误清除之后所有改变的项
int changedx=numX[clear];
int changedy=numY[clear];
result[changedx][changedy]=0;
}
count--;
}
}
return result;
}
test方法逻辑
test方法进行行列测试(当阶数为4,6,8,9时额外进行宫测试)
public static boolean test(int[][] problem,int x,int y,int rank) {
int flagx=0;
int flagy=0;
int xr=0;
int yr=0;
int flagr=0;
for(int i=0;i<rank;i++) {//行测试
if(problem[x][y]==problem[i][y]) {
flagx++;
}
}
if(flagx==2) {
return false;
}
for(int i=0;i<rank;i++) {//列测试
if(problem[x][y]==problem[x][i]) {
flagy++;
}
}
if(flagy==2) {
return false;
}
switch(rank) {//宫测试初始化
case 4:
xr=2;
yr=2;
break;
case 6:
xr=2;
yr=3;
break;
case 8:
xr=4;
yr=2;
break;
case 9:
xr=3;
yr=3;
break;
default:
}
if(xr!=0) {//宫测试
for(int i=x-x%xr;i<x+xr-x%xr;i++) {
for(int j=y-y%yr;j<y+yr-y%yr;j++) {
if(problem[x][y]==problem[i][j]) {
flagr++;
}
}
}
if(flagr==2) {
return false;
}
}
return true;
}
文件流输出
输出部分
try {//输出结果
File file=new File(fileout);
BufferedWriter bw=new BufferedWriter(new FileWriter(file));
for(int times=0;times<results.size();times++) {
int[][] result=results.get(times);
for(int i=0;i<rank;i++) {
for(int j=0;j<rank;j++) {
bw.write(result[i][j]+"");
bw.write(" ");
}
bw.newLine();
bw.flush();
}
bw.newLine();
bw.flush();
}
bw.close();
}catch(Exception e) {
e.printStackTrace();
}
性能分析
测试
![案例测试](https://img2018.cnblogs.com/blog/1797453/201909/1797453-20190924215848104-1391967677.png)