软件工程实践2019第三次作业

GitHub项目地址

PSP表格

PSP Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 20 20
Estimate 估计这个任务需要多少时间 10 10
Development 开发 1260 1360
Analysis 需求分析 (包括学习新技术) 480 540
Design Spec 生成设计文档 30 10
Design Review 设计复审 30 20
Coding Standard 代码规范 (为目前的开发制定合适的规范) 30 10
Design 具体设计 30 90
Coding 具体编码 540 600
Code Review 代码复审 60 30
Test 测试(自我测试,修改代码,提交修改) 60 60
Reporting 报告 60 120
Test Repor 测试报告 30 60
Size Measurement 计算工作量 30 60
Postmortem & Process Improvement Plan 事后总结, 并提出过程改进计划 120 90
合计 1470 1600

解题思路

    看到题目后首先关心的是如何实现数独算法,因为以前没玩过数独所以特地下了app熟悉数独的规则和解法。初步了解后打算难度适中的9阶数独入手,成功完成9阶数独的算法后再实现3、5、6、7、8阶数独算法。
    接下来思考如何实现算法,想过创建三阶数组、记录每一个格子的可能数值和可能数值个数等,但是都没有深入写下去。后来上网查找数独解法相关资料看到有些熟悉DFS,回溯法,因为当初数据结构学的不太好,花了不少时间好好理解后,觉得理解后思路较简单且代码精简,就用深度优先算法来解决问题。

算法思路

//回溯法解数独         
private void backTrace(int i, int j) {   	
        if (i == m-1 && j == m) {
            System.out.println("获取正确解");            
            outputs();
            return;            
        }
        //已经到了列末尾了,还没到行尾,就换行
        if (j == m) {
            i++;
            j = 0;
        } 
        //如果i行j列是空格,那么才进入给空格填值的逻辑
        if (matrix[i][j] == 0) {       	 
            for (int k = 1; k <= m; k++) {
                //判断给i行j列放1-9中的任意一个数是否能满足规则
                if (check(i, j, k)) {
                    //将该值赋给该空格,然后进入下一个空格
                	//System.out.println( i+ " " + j + " " + k);
                    matrix[i][j] = k;
                    backTrace(i, j + 1);
                    <span style="color:red">//初始化该空格</span>.
                    //System.out.println("初始化");
                    //if(find==false)
                    matrix[i][j] = 0;                   
                }
            }
        } else {
            //如果该位置已经有值了,就进入下一个空格进行计算
            backTrace(i, j + 1);
        }
    }
    核心算法完成后将其完善,添加3、4、5、6、7、8阶数独的算法,不算难,可一定要注意6、8阶数独的宫区域,区域设置及检查的宫格不能搞混!我因为这个问题有debug了几个小时。。。
if(m==6) {
        	int tempRow = row / 2;//区域划分每行二区、每列三区!
	        int tempLine = line / 3;
	        for (int i = 0; i < 2; i++) {
	            for (int j = 0; j < 3; j++) {
	                if (matrix[tempRow * 2 + i][tempLine * 3 + j] == number) {
	                    return false;
	                }
	            }
	        }
        }
    算法结束了就开始按照要求写输入输出,一开始也是懵的呀。。。cmd输入?args[]?文件读写? 然后我就网上查命令行输入,正好微信群助教也在教学了一波,舍友实例助攻,所以这个还好。再然后就是查找Java的I/O流资料,每个字都看得懂,理解起来有点难,但问题也不大,就是不太好操作。。。读入文件并填充这个属实不太好搞,而且一下子读入几个数组怎么操作
    emmmm。。。后来还是参考了其他几个同学的输入。因为我一开始的想法是:把文件读入分装到inputs()函数,更具数独数n在循环里创建对象并进行回溯输出操作,一个数独稳稳当当,可在加一个就出问题了只能读取第一个数组,当时思维僵化,想半天不知道为什么烦躁的抓耳挠骚,还是询问舍友后再明白文件在循环里被重复读入,所以理所当然只能输出一个重复的答案。所以就把输入写到主函数里,没读一个数独矩阵就直接进行计算然后输出,虽然代码没有原来美观但我也没得办法。

一开始是这样子的

后来。。。

try { // 防止文件建立或读取失败,用catch捕捉错误并打印,也可以throw  
            /* 读入TXT文件 */  
            // 绝对路径或相对路径都可以,这里是绝对路径,写入文件时演示相对路径  
            File filename = new File(inputFileName); // 要读取以上路径的input.txt文件  
            InputStreamReader reader = new InputStreamReader(  
                    new FileInputStream(filename),"UTF-8"); // 建立一个输入流对象reader
            BufferedReader br = new BufferedReader(reader); // 建立一个对象,它把文件内容转成计算机能读懂的语言             
            //把盘面写入数组                            	  	    	
    	    	int ch;
    	        int i=0; int j=0;
    	        while ((ch = br.read()) != -1) {
    	            if ( (((char) ch) != '\n') &&(((char) ch) != ' ')) {  
    	            	if(i<m){
    	            		if(j<m){
    	            			if(ch!=13){
    	            				matrix[i][j]=((char) ch)-48;
    	            				j++;
    	            			}
    	            		}else{  
    	            			i++;
    	            			j=0;
    	            			matrix[i][j]=((char) ch)-48;
    	            		}
    	            	}    	            	
    	            	 if(i==m){
    	                     if(n!=0){
    	                         Sudoku s = new Sudoku(6);
    	                         s.backTrace(0, 0);
    	                         n--;
    	                         i=0;j=0;
    	                     }
    	            	 }   	          	 	    	            	
    	           }   	    		    	            	            	                	    	    	    	
    	      }
    	      br.close();
        } catch (Exception e) {  
            e.printStackTrace();  
        }

测试

各阶数独运行结果

Code Quality Analysis

    下载在eclipse中下载并配置checkstyle,进行代码质量分析
因为缩进符和含有制表符tab几乎全是黄的。。。一个个改过来了

性能分析工具Studio Profiling Tools

    学习使用jdk自带的性能分析工具jconsole

心路历程和收获

心路历程:题目好难啊——我好菜呀——我是不是不适合读计算机???——不交作业就没分数,硬着头皮干吧
心态就是一直炸。。。但是确实有不少的收获,命令行输入、io流、回溯算法、GitHub仓库。学到很多东西,也不断磨练我的心态,估计下次作业我也会继续炸,但是炸多了就会习惯的吧,毕竟还有那么多次作业。。。
这次写代码我发现很关键的就是:细节决定成败。好几次卡我的点都是应为一些自我感觉不会出问题的小地方,所以一定要谨慎谨慎又谨慎。还有就是要熟悉编译软件,真的可以极大提高编程效率。![]

posted @ 2019-09-25 21:35  _清欢  阅读(167)  评论(0编辑  收藏  举报