• 2020软件工程作业03


    这个作业属于哪个课程 https://edu.cnblogs.com/campus/zswxy/software-engineering-2017-1
    这个作业要求在哪里 https://edu.cnblogs.com/campus/zswxy/software-engineering-2017-1/homework/10494
    这个作业的目标 整一个解数独的玩意儿
    作业正文 如下
    其他参考文献

    1、Github项目地址

    https://github.com/Ayamegusa/20177717

    2、PSP表格

    PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
    Planning 计划 30 30
    Estimate 估计这个任务需要多少时间 30 30
    Development 开发 950 685
    Analysis 需求分析 (包括学习新技术) 60 40
    Design Spec 生成设计文档 0 0
    Design Review 设计复审 0 0
    Coding Standard 代码规范 (为目前的开发制定合适的规范) 0 0
    Design 具体设计 30 30
    Coding 具体编码 600 420
    Code Review 代码复审 60 15
    Test 测试(自我测试,修改代码,提交修改) 200 180
    Reporting 报告 70 85
    Test Repor 测试报告 30 25
    Size Measurement 计算工作量 10 10
    Postmortem & Process Improvement Plan 事后总结, 并提出过程改进计划 30 50
    合计 1050 800

    3、思路描述

    一拿到题目当场想到可以暴力解数独 但是又想到暴力解实在太可怕了x ...于是又去了解了关于求解数独的其他算法

    最后我寻思我大概也只配写写回溯法了... emmm 然后就选择了回溯法(嗯 就是这样

    4、设计实现过程

    • 代码图

    • main_

      文件的读取、打开操作 参数转换 数独求解以及异常处理

    • Parse

      参数转换的具体实现

    • Solve

      求解数独

    • PlaceNumber

      填入数字(数独的核心函数

    • Exists

      对各行各列以及各宫格的检查

    5、性能测试与优化

    • 性能测试

    大部分时间消耗在找数字上面

    • 已通过静态检查并消除警告

    • 优化

    看这架势要优化只能换算法了 (x_x
    ......所以优化暂时我也没有办法 orz

    只能之后再考虑了(没错

    6、异常处理说明

    • 参数转换

      缺少参数时提示缺少对应的某参数

    for (int i = 1; i < argc; i += 2)
    {
        param.insert(std::make_pair(argv[i], argv[i + 1]));
    }
    
    if (param.find("-m") != param.end())
    {
        m = std::stoi(param["-m"]);
    }
    else
    {
        throw std::exception("缺m");
    }
    
    if (param.find("-n") != param.end())
    {
        n = std::stoi(param["-n"]);
    }
    else
    {
        throw std::exception("缺n");
    }
    
    if (param.find("-i") != param.end())
    {
        input = param["-i"];
    }
    else
    {
        throw std::exception("缺i");
    }
    
    if (param.find("-o") != param.end())
    {
        output = param["-o"];
    }
    else
    {
        throw std::exception("缺o");
    }
    
    • 文件打开

      文件打开失败时给出相应提示

    auto ifp = fopen(input.c_str(), "r");
    if (ifp == nullptr)
    {
        throw std::exception("open input file failed");
    }
    
    auto ofp = fopen(output.c_str(), "w");
    if (ofp == nullptr)
    {
        throw std::exception("open output file failed");
    }
    
    • 文件打开单元测试
    TEST_METHOD(FileNotFound)
    {
        char* argv[] =
        {
            "",
            "-mi",
            "9",
            "-n",
            "1",
            "-ii",
            "test.i",
            "-o",
            "test.o"
        };
        try
        {
            main_(9, argv);
        }
        catch (std::exception& exception)
        {
            Assert::AreEqual("open input file failed", exception.what());
        }
    }
    

    7、核心代码说明

    大概整个求解程序的核心就是PlaceNumber函数辽(填数字

    void PlaceNumber(Map& map, int m, int i)
    {
        //坐标是否位于map终点
        if (i >= m * m)
        {
            throw std::exception("Finished!");
        }
    
        //当前坐标是否需要填入数字
        if (map[i] > 0)
        {
            PlaceNumber(map, m, i + 1);
            return;
        }
    
        //遍历待填数字
        for (int n = 1; n <= m; ++n)
        {
            //待填数字是否存在
            if (!Exists(map, m, n, i % m, i / m))
            {
                map[i] = n;
                PlaceNumber(map, m, i + 1);
                map[i] = 0;
            }
        }
    }
    
    • 流程图

    (画这个流程图的时候我纠结了很久 因为平时也不太画流程图 都不知道该如何处理关于回溯以及Undo操作的体现 最后还是找tw神仙帮我解决了这个问题

    8、单元测试

    9x9单元测试

    TEST_METHOD(Sudoku9x9)
    {
        Map mp
        {
            0,0,6,7,0,3,5,0,0,
            0,0,0,0,4,0,0,0,0,
            5,0,0,0,0,0,0,0,2,
            9,0,0,0,0,0,0,0,7,
            0,3,0,0,0,0,0,4,0,
            8,0,0,0,0,0,0,0,1,
            1,0,0,0,0,0,0,0,4,
            0,0,0,0,0,0,0,0,0,
            0,5,9,2,6,7,3,1,0
        };
        Map res
        {
            2,4,6,7,1,3,5,8,9,
            7,9,8,5,4,2,1,6,3,
            5,1,3,6,8,9,4,7,2,
            9,2,4,1,5,6,8,3,7,
            6,3,1,9,7,8,2,4,5,
            8,7,5,3,2,4,6,9,1,
            1,6,7,8,3,5,9,2,4,
            3,8,2,4,9,1,7,5,6,
            4,5,9,2,6,7,3,1,8
        };
        Solve(mp, 9);
        Assert::IsTrue(std::equal(mp.begin(), mp.end(), res.begin()));
    }
    

    除此之外 单元测试包含了以下项(共10个单元测试

    • 3x3
    • 4x4
    • 5x5
    • 6x6
    • 7x7
    • 8x8
    • 无解
    • 文件输入输出
    • 文件不存在

    9、运行

    • 3x3

    • 4x4

    • 5x5

    • 6x6

    • 7x7

    • 8x8

    • 9x9

    10、心路历程与收获

    草莓毛巾卷真好次(我真的没有在做作业的时候吃甜点 真的

    看到题目的时候就觉得巨麻烦 但迫于作业还是要着手去写 后来关于参数处理的那部分操作去请教了tw神仙 最后总算是赶在ddl之前完成了作业 整个作业大部分时间都花在了debug 老师在博客作业里的要求非常多也非常杂 一项项完成下来也不知道自己到底有没有完成所有需要完成的东西(希望我没有落下什么重要的部分
    然后其实不管是什么事情大概只要着手去做好像也不会有自己想象中那么难 真正开始去做才是最难的x

    (最后 感谢tw神仙提供的帮助 下次窝请你次毛巾卷

  • 相关阅读:
    uni-app 版本更新控制
    Chrome为什么打开一个页面,会有4个进程?
    vue 导航栏滚动吸顶
    vue 运行后, sass 报错
    HAProxy——HAProxy、Nginx、LVS优势劣势 (转)
    HAProxy——关于配置的备份
    RabbitMQ——用HAProxy实现负载均衡
    docker——Docker常见问题总结 (转)
    docker——docker容器内存和CPU使用限制
    docker——用docker-compose安装redis
  • 原文地址:https://www.cnblogs.com/murasaki/p/12577885.html
Copyright © 2020-2023  润新知