2020软件工程作业03
这个作业属于哪个课程 | 2018软件工程 |
---|---|
这个作业要求在哪里 | 作业要求 |
这个作业的目标 | 测试编程能力及自学能力 |
其他参考文献 | 空 |
解题思路:
九宫格以前做过类似的题目,就是用穷举递归和逐个比较,这是最暴力最简单的做法。我第一份代码就是用暴力解析求出格子应放数字。不过在做的过程中,发现可以用空间换时间,还不知效率如何正在考虑。
设计实现过程
一个主类,多个方法。因为几乎所有函数都会用到宫格数组,所以把数组作为类变量给全部方法共享。
函数联系及分析:
主方法中只需要处理参数异常,调用输入输出方法。
由输入输出方法调用fill()方法实现主要功能。
fill()方法是核心方法,是一个递归主体方法。在其中调用其他方法确定行和列(ergodiclinecol(int line,int col))、宫格中的宫中(around(int order,int line ,int col))没有重复数字。最后填充完毕后把宫格数组输出到输出文件中(print(BufferedWriter writer))。
关键函数是否需要画出流程图?
我觉得不需要,递归函数都应该能看明白,穷举也应该懂。其他的逐个比较遍历就更轻松简单了。
单元测试是怎么设计的?
正确测试用例:用上述代码稍作修改,穷举输出3-9阶的所有宫格数字排列,在其中随机挑选出两个测试用例进行修改测试。
九宫格
八宫格
七宫格
六宫格
五宫格
四宫格
三宫格
错误测试用例:少参数测试
多参数测试
参数m的值测试
参数n的值和文件中的数组个数不同测试(n超出文件中数组个数会报错,原因是空字符串)
改进程序性能上所花费的时间,描述你改进的思路。
改进的话主体还应是递归主体,但是可以从最小空闲数字的行或者列开始递归穷举(不需要从第一行第一列开始),穷举也不需要从1-m穷举(而是从空闲的最小值开始穷举,后面类中包含)。
可以对宫格数组做初始化处理,每一行和每一列都有一个类(两个一维对象数组):记录空闲多少个数字,分别是哪几个数字(数组或者arraylist的形式),第一个空闲的位置。
这样就能减少许多不必要的计算和逐个比较。
关键代码,并解释思路与注释说明。
public static void inout(String mchar,String nchar,String in,String out ) throws IOException { //输入输出控制
reader=new BufferedReader(new FileReader(new File(in)));
writer= new BufferedWriter(new FileWriter(new File(out)));
m = Integer.valueOf(mchar);
if(m<3||m>9) {
writer.write("宫格阶数错误!dong?");
writer.close();
System.exit(0);
}
n = Integer.valueOf(nchar);
String str = null;
char[] chars=null;
for(int l=0;l<n;l++) { //进行n次数组读取
int i=0;
for(int order=0;order<m;order++){ //读取文件中的行
str = reader.readLine().trim(); //删除任何前导和尾随空格
chars=str.toCharArray();
int k=0;
for(int j=0;j<chars.length;j+=2) { //从字符数组中提取出数字
lattice[i][k++]=chars[j]-'0';
}
i++;
}
reader.readLine(); //读完一个数组需要读出数组间的回车
fill(0,0);//调用fill函数进行填充数字
}
reader.close(); //使用完关闭缓冲
writer.close(); //使用完关闭缓冲(把数据写入到文件中)
}
public static void fill(int line,int col) throws IOException { //递归主体
if(line==m) { //递归出口
print(writer);
return ;
}
if(lattice[line][col]==0) { //当前位置没有数字
for(int k=1;k<=m;k++) { //从一到m穷举
lattice[line][col]=k;
if(ergodiclinecol(line,col)&&around(m,line,col)) { //判断数字是否符合题意
if(col<m-1) {
fill(line,col+1); //递归下一列
}else {
fill(line+1,0); //当前是列尾,递归下一行第一列
}
}
}
lattice[line][col]=0; //当前数字造成后面数字不合题意,重新置0,返回上一层
}else {
if(col<m-1) {
fill(line,col+1); //递归下一列
}else {
fill(line+1,0); //当前是列尾,递归下一行第一列
}
}
}
public static boolean ergodiclinecol(int line,int col) { //遍历填数字的格子行列有无相同数字,有则返回false
int[] linenum=new int[m+1]; //记录行数字被找到次数
int[] colnum=new int[m+1]; //记录列数字被找到次数
for(int i=0;i<m;i++) { //遍历行列
if(lattice[line][i]!=0) { //宫格数组值为零不参加寻找
if(linenum[lattice[line][i]]==0) { //数字没被找到过,修改值为1(设置为被找到过)
linenum[lattice[line][i]]=1;
}else {
return false; //数字被找到过,出现两次,返回false
}
}
if(lattice[i][col]!=0) {
if(colnum[lattice[i][col]]==0) {
colnum[lattice[i][col]]=1;
}else {
return false;
}
}
}
return true;
}
public static int location(int linecol ,int highwide) {//通过参数定位处于哪个宫,返回宫的起始横或者纵坐标
int result=(linecol+1)/highwide;
int yushu=(linecol+1)%highwide;
if(yushu>=1) {
result=result*highwide;
}else {
result=(result-1)*highwide;
}
return result;
}
public static boolean ergodic(int wide,int high,int col,int line) {//遍历宫内是否有相同数字,有则返回false
int[] nums=new int[10];
for(int i=line;i<line+high;i++) {
for(int j=col;j<col+wide;j++) {
if(lattice[i][j]!=0) {
if(nums[lattice[i][j]]==0) {
nums[lattice[i][j]]=1;
}else {
return false;
}
}
}
}
return true;
}
public static void print(BufferedWriter writer) throws IOException {//把数组写入到文件
for (int i = 0; i < m; i++) {
for (int j = 0; j < m; j++) {
writer.write(lattice[i][j]+"");
if(j<m-1) writer.write(" ");
}
writer.write("\n");
}
writer.write("\n");
}
心路历程与收获。
原设计文档:
下次我的设计文档一定要写的更详细一些,这三两句话就把题目解出来了,但是代码设计依赖于这几句话太难写了。太多的具体设计和数据结构不能统一使得我花费了好长时间依旧毫无进展,回顾代码也发现越来越多的不足之处。
立下flag,设计文档一定要详细!!
时间 | 链接 |
---|---|
2020/7/28 | 2020软件工程作业01 |
2020/7/30 | 2020软件工程作业02 |
2020/8/6 | 2020软件工程作业03 |