zoukankan      html  css  js  c++  java
  • fighting

    Github地址

                     <tr align=center>
    		<td>Estimate</td><td>这个任务需要多少时间</td><td>24小时</td><td>36小时</td>		
    	</tr>
                                   <tr align=center>
    		<td>Development</td><td>开发</td></td><td>8小时</td><td>12小时</td>		
    	</tr>
                                   <tr align=center>
    		<td>Analysis</td><td>需求分析(包括学习新技术)</td><td>2小时</td><td>3小时</td>		
    	</tr>
                                   <tr align=center>
    		<td>Design Spec</td><td>生成设计文档</td></td><td>2小时</td><td>4小时</td>		
    	</tr>
                                   <tr align=center>
    		<td>Design Review</td><td>设计复审</td></td><td>3小时</td><td>2小时</td>		
    	</tr>
                                   <tr align=center>
    		<td>Coding Standard</td><td>代码规范</td></td><td>1小时</td><td>3小时</td>		
    	</tr>
                                   <tr align=center>
    		<td>Design</td><td>具体设计</td></td><td>1小时</td><td>40分钟</td>		
    	</tr>
                                   <tr align=center>
    		<td>Coding</td><td>具体编码</td></td><td>6小时</td><td>4小时</td>		
    	</tr>
    	<tr align=center>
    		<td>Code Review</td><td>代码复审</td></td><td>5小时</td><td>3小时</td>		
    	</tr>
                     <tr align=center>
    		<td>Test</td><td>测试(自我测试,修改代码,提交修改)</td><td>1小时</td><td>2小时</td>	
    	</tr>
                                   <tr align=center>
    		<td>Reporting</td><td>报告</td></td><td>1小时</td><td>2小时</td>		
    	</tr>
                                   <tr align=center>
    		<td>Test Repor</td><td>测试报告</td></td><td>1小时</td><td>2小时</td>		
    	</tr>
                                   <tr align=center>
    		<td>Size Measurement</td><td>计算工作量</td></td><td>1小时</td><td> 1小时</td>		
    	</tr>
                                   <tr align=center>
    		<td>Postmortem</td><td>事后总结,并提出过程改进计划</td></td><td>2小时</td><td> 1小时</td>		
    	</tr>
                                   <tr align=center>
    		<td>Improvement Plan</td><td>过程改进计划</td></td><td>2小时</td><td> 2小时</td>		
    	</tr>
                                   <tr align=center>
    		<td>合计</td><td></td></td><td> 38小时</td><td> 40小时40分钟</td>		
    	</tr>
    
    PSP表格
    Personal Software Process Stages预估耗时实际耗时
    Planning计划2小时1小时

    需求

    实现一个命令行程序,不妨称之为Sudoku

    百度百科简介:

    数独盘面是个九宫,每一宫又分为九个小格。在这八十一格中给出一定的已知数字和解题条件,利用逻辑和推理,在其他的空格上填入1-9的数字。使1-9每个数字在每一行、每一列和每一宫中都只出现一次,所以又称“九宫格”。

    具体任务:

    现在我们想一步一步来,完成从三宫格到九宫格的进阶;完成三宫格和其他博客任务,就算过了初级考核,其他的算升级。具体各阶规则如下:

    输入:

    输入文件名以命令行参数传入。例如我们在命令行窗口(cmd)中进入Sudoku.java所在文件的目录然后输入:

    javac Sudoku.java
    java Sudoku -m 9  -n 2  -i input.txt  -o output.txt
    
    -m 宫格阶级(3~9的整数)
    -n 待解答盘面数目
    -i 指定输入文件(需要在自己的电脑磁盘里面提前创建好)
    -o 指定程序的输出文件(也需要在自己的电脑里面提前创建好)
    

    上面语句对应的输入文件如下:

    0 0 8 0 0 4 0 0 9
    0 6 0 0 0 0 1 0 0
    0 3 7 0 0 0 0 0 0
    8 0 1 2 6 9 0 0 3
    0 2 5 4 7 0 0 6 8
    0 9 0 0 0 5 0 0 0
    9 0 0 1 5 2 3 7 4
    0 4 0 3 9 8 0 1 6
    1 5 3 6 4 7 8 0 2
    
    2 0 0 0 0 0 0 0 0
    0 0 6 3 0 0 0 7 0
    5 0 0 0 0 0 1 0 0
    9 6 7 4 0 0 0 0 5 
    8 1 3 0 0 0 0 0 0
    4 2 0 7 1 8 9 6 3 
    3 5 0 0 4 1 6 9 7
    6 9 8 2 7 3 5 4 1
    0 4 0 0 5 9 2 0 8
    

    输出

    输出n个程序解出的盘面,每两个盘面间空一行,每个盘面中,每两个小格之间有一个空格。

    上面的命令行对应的输出文件output.txt组织如下:

    5 1 8 7 2 4 6 3 9
    2 6 9 5 8 3 1 4 7
    4 3 7 9 1 6 2 8 5
    8 7 1 2 6 9 4 5 3
    3 2 5 4 7 1 9 6 8
    6 9 4 8 3 5 7 2 1 
    9 8 6 1 5 2 3 7 4
    7 4 2 3 9 8 5 1 6
    1 5 3 6 4 7 8 9 2
    
    2 7 9 1 8 4 3 5 6
    1 8 6 3 2 5 4 7 9
    5 3 4 9 6 7 1 8 2
    9 6 7 4 3 2 8 1 5
    8 1 3 5 9 6 7 2 4
    4 2 5 7 1 8 9 6 3
    3 5 2 8 4 1 6 9 7
    6 9 8 2 7 3 5 4 1 
    7 4 1 6 5 9 2 3 8
    

    解题思路:

    拿到题目的时候其实没有看懂到底要求做什么,对于命令行传入参数也是一无所知,在群里面询问大佬们,了解命令行如何传参之后,才正式开始构思如何求解九宫格盘面,好在自己平时也喜欢玩数独,给我一个九宫格的盘面30分钟不到就能解完,可如今要自己来手写代码,让代码来解读,这到难倒我了,以自己目前的水平和知识面,写完估计的要300分钟吧!废话不多说了,先讲讲自己的思路吧:首先我们得知道3-9宫格最终盘面里每个数字所应满足的要求:

    三宫格:盘面是3*3。使1-3每个数字在每一行、每一列中都只出现一次,不考虑宫;
    四宫格:盘面是2*2四个宫,每一宫又分为2*2四个小格。使1-4每个数字在每一行、每一列和每一宫中都只出现一次;
    五宫格:盘面是5*5。使1-5每个数字在每一行、每一列中都只出现一次,不考虑宫;
    六宫格:盘面是2*3六个宫,每一宫又分为3*2六个小格。使1-6每个数字在每一行、每一列和每一宫中都只出现一次;
    七宫格:盘面是7*7。使1-7每个数字在每一行、每一列中都只出现一次,不考虑宫;
    八宫格:盘面是4*2八个宫,每一宫又分为2*4八个小格。使1-8每个数字在每一行、每一列和每一宫中都只出现一次;
    九宫格:盘面是3*3九个宫,每一宫又分为3*3九个小格。使1-9每个数字在每一行、每一列和每一宫中都只出现一次;
    

    根据这个要求写一个方法legal,以判断在九宫格中的坐标(x,y)的位置上插入value,是否符合上述规则,代码如下

        public static Boolean legal(int a[][],int x, int y, int value,int m) {
     
            for (int i = 0; i < m; i++) {
                //如果列中有value,则返回false
                if (i != x && a[i][y] == value) {
                    return false;
                }
                //如果行中有value,则返回false
                if (i != y && a[x][i] == value) {
                    return false;
                }
            }
            if(m==9){
                //(minX,minY)是(x,y)所属小九宫格的左上角的坐标
                int minX = x / 3 * 3;
                int minY = y / 3 * 3;
         
                for (int i = minX; i < minX + 3; i++) {
                    for (int j = minY; j < minY + 3; j++) {
                        //如果小九宫格中的非(x,y)的坐标上的值为value,返回false
                        if (i != x && j != y && a[i][j] == value) {
                            return false;
                        }
                    }
                }
            }
            if(m==4){
                //(minX,minY)是(x,y)所属小4宫格的左上角的坐标
                int minX = x / 2 * 2;
                int minY = y / 2 * 2;
    
                for (int i = minX; i < minX + 2; i++) {
                    for (int j = minY; j < minY + 2; j++) {
                        //如果小九宫格中的非(x,y)的坐标上的值为value,返回false
                        if (i != x && j != y && a[i][j] == value) {
                            return false;
                        }
                    }
                }
            }
            if(m==8){
                //(minX,minY)是(x,y)所属小8宫格的左上角的坐标
                int minX = x / 4 * 4;
                int minY = y / 2 * 2;
         
                for (int i = minX; i < minX + 4; i++) {
                    for (int j = minY; j < minY + 2; j++) {
                        //如果小九宫格中的非(x,y)的坐标上的值为value,返回false
                        if (i != x && j != y && a[i][j] == value) {
                            return false;
                        }
                    }
                }
            }
            if(m==6){
                //(minX,minY)是(x,y)所属小6宫格的左上角的坐标
                int minX = x / 2 * 2;
                int minY = y / 3 * 3;
         
                for (int i = minX; i < minX + 2; i++) {
                    for (int j = minY; j < minY + 3; j++) {
                        //如果小九宫格中的非(x,y)的坐标上的值为value,返回false
                        if (i != x && j != y && a[i][j] == value) {
                            return false;
                        }
                    }
                }
            }
            return true;
        }
    

    legal方法写完之后,并没有结束,求解九宫格的核心思想让我为之思考了一整天,首先想到的是按照平时玩数独的思维来解答:也就是自己常用的排除法,先将每行每列每个宫里面不可能出现的数字排除掉,然后将一些确定的数字填上去,然后再排除,再填......显然这种方法就是没脑子的人才会想的出来的,写完估计都猴年马月了,于是去询问ACM的算法大佬,提示了我一下,让我使用回溯法,刚提完,我瞬间“柳暗花明又一村”,马上有了思路:

    具体代码和注释如下:

    shuDu[][]是用来存放数独游戏的二维数组。

    public static int shuDu[][] = new int[9][9];
        public static void setShuDu(int[][] shuDu) {
            Sudu.shuDu = shuDu;
        }
    

    使用回溯法求解数独

        public static void shuDu_solution(int k,int m) throws IOException {
            if (k == (m*m)) {
              String src= "D:\sudoku\"+outputFilename;
                try{
                FileWriter fw = new FileWriter(src,true);
                for(int i=0;i<m;i++){
                    for(int j=0;j<m;j++){ 
                    	fw.write(shuDu[i][j]+" ");
    
                    }
    
                    fw.write("
    ");
                }
                fw.write("
    ");
                fw.close(); // 最后记得关闭文件  
                }
                catch (Exception e) {  
                    e.printStackTrace();  
                }  
                return;
            }
            int x = k / m;
            int y = k % m;
            if (shuDu[x][y] == 0) {
                for (int i = 1; i <= m; i++) {
                    shuDu[x][y] = i;
                    if (legal(shuDu,x, y, i,m)) {
                        shuDu_solution(k + 1,m);
                    }
                }
                shuDu[x][y] = 0;
            } else {
                shuDu_solution(k + 1,m);
            }
        }
    

    初始化命令行的传入的参数

        public static void loadArgs(String args[]){
        	if(args.length>0&&args!=null){
        		for(int i=0;i<args.length;i++){
        			switch (args[i]) {
    				case "-i":
    					inputFilename = args[++i];
    					break;
    				case "-o": 
    					outputFilename = args[++i];
    					break;
    				case "-m": 
    					m=Integer.valueOf(args[++i]);
    					break;
    				case "-n":
    					n=Integer.valueOf(args[++i]);
    				    break;
    
    				default:
    					break;
    				}
        		}
        	}
        }
    

    最后就是主函数

     public static void main(String[] args) throws IOException {
        	loadArgs(args);
        	int generateShuDu[][]=new int[10][10];   
    		File myFile = new File("D:\sudoku",inputFilename);
    		Reader reader = new InputStreamReader(new FileInputStream(myFile),"UTF-8"); 
    		int tempchar;  int i=0; int j=0;
    		    while ((tempchar = reader.read()) != -1) {  
    		    if ( (((char) tempchar) != '
    ') &&(((char) tempchar) != ' ')) {  
    		        if(i<m){
    		        	if(j<m){
    		        		if(tempchar!=13){
    		        			generateShuDu[i][j]=((char) tempchar)-48;
    			        		j++;
    		        		}
    		        	}else{	
    		        		i++;
    		        		j=0;
    		        		generateShuDu[i][j]=((char) tempchar)-48;
    		        	}
    		        }
    		        if(i==m){
    		        	if(n!=0){
    			            setShuDu(generateShuDu);
    			            shuDu_solution(0,m);
    			            n--;
    			            i=0;j=0;
    		        	}
    		        	
    		        }
    		    }  
    		}
    		reader.close();
        }   
    

    遇到的问题(这个问题耽误了我6个小时左右):

    FileWriter fw = new FileWriter("c.txt",true);
    fw.write("hello");
    fw.close();
    

    文件写入建议用FileWriter

    如果用BufferedWriter会导致多次写入时被覆盖!

    String outfile="D:\sudoku\out.txt";
    File writename = new File(outfile); // 相对路径,如果没有则要建立一个新的out.txt文件  
    writename.createNewFile(); // 创建新文件  
    BufferedWriter out = new BufferedWriter(new FileWriter(writename)); 
    out.write(shuDu[i][j]+" ");
    

    异常处理:主要是对文件的读取进行异常处理




    单元测试样例:

    性能测试截图():



    性能测试我使用的是jprofiler9.2,由于是刚开始接触这个插件,对其一些功能还不太熟悉,研究了一个晚上,还是看不懂数据,不知道类方法耗时在哪里体现,后面再花时间去摸索(仅仅下载这个插件和主程序,然后配置成功到运行,就花了一天时间,我太难了,关键是看不懂这个图上的数据)

    最后总结一下:

    用java开发感觉if-else流程语句和一些基本语法没有太大的问题,主要是一些常用的类(文件处理类,IO流)使用还不太熟练,导致开发效率低,中途遇到各种各样的bug,以至于气的连晚饭都不想吃了,但自己还是坚持做完了,bug也解决了;除此之外,编辑器的使用也不太熟练,一些类似于命令行传参的细节性的问题也不懂,不过现在懂了,也算是一份收获吧,另外,学会了在github上面上传文件和文件夹,对于github的使用有了初步的认识,希望自己在下次的项目开发中有新的收获,遇到bug不要难过,要勇于挑战bug这样才能不断突破自己!

  • 相关阅读:
    作业20170928--2 单元测试
    作业20170928—1代码规范,结对要求
    第三周PSP
    20170922-3 功能测试作业
    第二周PSP
    采用c#实现功能1
    linux下搭建生成HLS所需的.ts和.m3u8文件
    android编译ffmpeg+x264
    ubuntu.sh: 113: ubuntu.sh: Syntax error: "(" unexpected
    解决:[WARNING] fpm_children_bury(), line 215: child 2736 (pool default) exited on signal 15 SIGTERM after 59.588363 seconds from start
  • 原文地址:https://www.cnblogs.com/lohh/p/11557591.html
Copyright © 2011-2022 走看看