zoukankan      html  css  js  c++  java
  • 2020软件工程作业03

    这个作业属于哪个课程 https://edu.cnblogs.com/campus/zswxy/software-engineering-2017-1
    这个作业要求在哪里 https://edu.cnblogs.com/campus/zswxy/software-engineering-2017-1/homework/10494
    这个作业的目标 编写程序实现数独填充
    作业正文 如下所示
    其他参考文献 www.baidu.com



    作业地址:

    https://github.com/EngulfMiss/20177701


    PSP2.1 Personal Software Process Stages 预估耗时 实际耗时
    Planning 计划 30分钟 1小时
    Estimate 估计这个任务需要多少时间 16小时 24小时
    Development 开发 6小时 8小时
    Analysis 需求分析 (包括学习新技术) 1小时 3小时
    Design Spec 生成设计文档 30分钟 1小时
    Design Review 设计复审 1小时 1小时
    Coding Standard 代码规范 (为目前的开发制定合适的规范) 30分钟 20分钟
    Design 具体设计 1小时 45分钟
    Coding 具体编码 5小时 14小时
    Code Review 代码复审 30分钟 30分钟
    Test 测试(自我测试,修改代码,提交修改) 30分钟 1小时
    Reporting 报告 2小时 2.5小时
    Test Repor 测试报告 30分钟 30分钟
    Size Measurement 计算工作量 30分钟 1小时
    Postmortem & Process Improvement Plan 事后总结, 并提出过程改进计划 30分钟 30分钟
    合计 24小时 41小时



    思路描述:

    1.数独可以看成是一个m*m的二维数组。
    2.能找到这个二维数组中为0的数字,及要填的数字。
    3.能够填入合适的数字,及行列不重复出现,如果有宫还有判断宫。


    实现过程:

    • 1.主函数main()
    • 2.遍历数独函数
    • 3.插入数检测函数
    • 4.读取文件函数
    • 5.输出函数


    解题思路

    循环遍历数组,找到数组中为0的位置,调用检测函数,找到一个可以填入该位置的最小满足条件数 ,将满足
    条件的数填入数组后重新遍历数组,找到下一个为0的数字,填数;如果某次填数发现可以填的数大于了数独
    规模数,说明这次填数失败,将当前位置还原为0,找到上一个填数位置换成下一个满足条件的数字,重新遍历
    数组,如果上一个位置也超出数独规模,就修改上上次,以此类推。递归遍历。


    整体流程图

    主要函数:

    数字检测函数checkNum() (包括检查行,列,宫)

    其中宫中的判断相对与行列会稍微复杂一些,需要通过具体的切分方法来判断确定

    每个点在哪个宫中,并确定各个宫的起点才好遍历宫。

         /**
         *
         * @param maze 需要填数的数独数组
         * @param i 当前位置的行
         * @param j 当前位置的列
         * @param x 带宫数独是如何切分的(切成多少行)
         * @param y 带宫数独是如何切分的(切分成多少列)
         * @return 行,列,(宫)都满足要求返回true,有一个不满足就返回false
         */
           static boolean checkNum(int[][] maze,int i,int j,int x,int y) {
            int num = maze[i][j];
            for (int k = 0; k < len; k++) {
                if (k == j) {
                    continue;
                } else if (maze[i][k] == num) {
                    return false;
                }
            }
    
            for (int k = 0; k < len; k++) {
                if (k == i) {
                    continue;
                } else if (maze[k][j] == num) {
                    return false;
                }
            }
    
            if((x != 0)&&(y != 0)){
                int bi = (i / (len / x)) * (len / x);
                int bj = (j / (len / y)) * (len / y);
                for (int k = bi; k < bi + (len / x); k++) {
                    for (int l = bj; l < bj + (len / y); l++) {
                        if ((k == i) && (l == j)) {
                            continue;
                        }
                        if (maze[k][l] == num) {
                            return false;
                        }
                    }
                }
            }
            return true;
        }
    




    遍历插入合适数函数insertNum()

    程序的核心部分,遍历数独,找0填入合适数,再递归调用本身。

    直到全部填完返回true。


        /**
         *
         * @param maze 需要遍历的数独数组
         * @param i 当前位置的行
         * @param j 当前位置的列
         * @param x 带宫数独是如何切分的(切成多少行)
         * @param y 带宫数独是如何切分的(切分成多少列)
         * @param inNum 想填入的数字
         * @return 全部填完返回true,填的数字超过最大可取数返回false
         */
            static boolean insertNum(int[][] maze, int i, int j, int x, int y, int inNum) {
            //寻找需填充的格子
            while (maze[i][j] != 0) {
                if (j < len - 1) {
                    j++;
                }
                else if (i < len - 1) {
                    i++;
                    j = 0;
                } else {
                    //填充完毕
                    return true;
                }
            }
            //填充尝试
            for (int k = 1; k <= inNum; k++) {
                maze[i][j] = k;
                if (len != 3){
                    if (checkNum(maze, i, j, x, y)) {
                        if (!insertNum(maze, i, j, x, y, inNum)) {
                            continue;
                        }
                        return true;
                    }
                }else{
                    if (cheackNum3(maze, i, j)) {
                        if (!insertNum(maze, i, j, -1, -1, NUM_9)) {
                            continue;
                        }
                        return true;
                    }
                }
            }
            maze[i][j] = 0;
            return false;
        }
    



    代码规范检查:

    修改方法:
    1.给每个常数定义成参量。

    2.把自定义函数中间的短横线'_'去掉了。

    3.添加作者信息。


    修改后:




    性能分析:

    好难看懂。只能自己分析了,既然是使用的递归insertNum()函数和checkNum()函数使用肯定是比较多的,
    想要提高性能,减少这两个函数的使用次数肯定对程序的整体性能提升很大。

    实施的改进:
    本来是行,列,宫我写了3个函数来分别判断,将三个判断函数的结果相与得到最终的结果。
    其实不用这么麻烦,完全可以把它们3个结合起来,因为只要有false,最终的判断结果就
    会是false。那么只要把它们3写在一个判断函数中,有不重复的数字出现直接就可以返回
    false了,就不用再进行其他判断了。减少判断的次数。




    测试:

    程序我还没有完成对n次的处理,因此n只能是一个,后续学习再完善


    3宫格

    4宫格

    5宫格

    6宫格

    7宫格

    8宫格

    9宫格




    心得与体会

    1.一开始看到题目要求命令行输入,我第一反应是想用C或C++。
    刚好在B站大学自学了几天C++,就像先试一下。但过了几天计划以失败告终,原因
    好像是,我动态分配的二维数组没有及时清理缓存,发生了内存溢出。

    以下是一些失败的尝试

    发生内存溢出后,我决定全部重来,改用Java。虽然C++失败了,可能是我想的太复杂,但思路是可行的,重新用java写的
    时候,可能是休息了一下清醒了一些。好像开悟了一点点,发现不需要很复杂的定位位置。

    命令行的输入还是问了别人的,文件的输入输出也是网上参考了一些资料。C++尝试的失败也
    说明自己还有很多地方需要学习。很多东西都还是不懂,需要花时间去了解。

    性能分析这些工具也还要去了解一下。


  • 相关阅读:
    Eclipse/MyEclip中使用复制粘贴功能很卡
    ActiveMQ使用教程
    ActiveMQ常见消息类型
    推荐12个最好的 JavaScript 图形绘制库
    eclipse 打包springboot成jar
    CentOS 7下ELK(6.2.4)++LogStash+Filebeat+Log4j日志集成环境搭建
    elasticsearch启动常见错误
    使用haproxy实现负载均衡集群
    linux配置mysql5.6 主主复制同步
    力扣No.102 二叉树的层次遍历
  • 原文地址:https://www.cnblogs.com/GinsoTree/p/12566696.html
Copyright © 2011-2022 走看看