博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
软件工程第二次作业
阅读量:5308 次
发布时间:2019-06-14

本文共 5450 字,大约阅读时间需要 18 分钟。

第二次作业个人项目实战


github


泛泛而谈的理解

我刚开始打代码的时候觉得打完就好,能过样例就ok。经历过一段时间后会发现有可能样例过了其他测试点全错,所以就会开始多测试几组数据,希望自己的代码能够尽量准确。当准确性开始有保障后,我就会去思考程序本身是不是可以进一步改进,使代码运行速度变的更快。在我看来自己出数据测试就相当于书中说的单元测试,回归测试。不过这种测试变得更加的规范化。而自己对代码的不断改进的过程则相当于书中的效能分析,不过通过效能分析工具使我们对代码有更细致的了解,从而是我们能快速的发现代码中的瓶颈从而改进。

关于个人软件开发流程(psp)这个东西我是第一次了解到。通过书中的大学生和工程师的psp的对比。我发现工作越久,需求分析以及测试花费的时间会越来越多。所以我想我们应该更注重这些方面。而不只是专注于具体的编码。

* * *

遇到的困难及解决方法

看到这个题目,第一反应就是搜索。接着我就去网上搜索了一些有关数独的资料,发现构造数独基本上就是两种方法,一个就是深度优先搜索,另一个则是先填中间的宫然后通过置换行列得出所有得宫的数字。我个人觉得深度优先搜索的写法更简洁明了,所以我就用了搜索去写。

整个代码写下来基本上没有什么问题。但是运行后就发现跑的特别慢,用了一分钟左右才跑完。通过性能测试分析,输出函数占用了大部分时间。根据以前的经验知道puts,gets,putchar,getchar这些方法的输入输出会比scanf,printf快很多,所以我就修改了输出函数,使用puts把一整个数独当作一个字符串来进行输出。

代码如下

void generator::print(){    int cnt = 0;    for (int i = 1; i <= 9; i++)    {        for (int j = 1; j <= 9; j++)        {            ch[cnt++] = shudu[i][j];            ch[cnt++] = ' ';        }        ch[cnt++] = '\n';    }    puts(ch);}

经过修改后的代码需要大概6秒钟的时间可以输出1000000组答案。下图是最终代码的性能测试分析的一张截图,输出函数print只占用了很小的一部分了。

修改后代码的性能分析图,耗时最大的部分就是后面展示的关键代码。

885624-20170910013310507-2121098194.png


关键代码or设计说明

运行成功的截图,生成了170m大小的sudoku.txt文件

885624-20170910153904429-756522185.png

关键代码

for (int i = 1; i <= 9; i++){    if (!c[x][i] && !r[y][i] && !b[box][i])    {        c[x][i] = true; r[y][i] = true; b[box][i] = true;        shudu[x][y] = i + 48;        get(x, y + 1);        c[x][i] = false; r[y][i] = false; b[box][i] = false;    }}

这是深度搜索中的关键代码,这个搜索函数只有两个参数表示当前在数独的哪个位置。c,r,b三个数组则分别表示的是行,列,宫里面的数字存在情况,例如c[1][1] = true 就表示第一行的数字1已经存在。

对这个代码我进行了单元测试,测试成功了,但是不知什么原因一直代码覆盖率一直为0,显示生成的二进制文件为空,到现在暂时还没有解决...

下面给出单元测试的代码

#include "stdafx.h"#include "CppUnitTest.h"#include "E:/软件工程/sudokuproject/sudokuproject/sudokuproject/Generator.h"#include 
#include
#include
using namespace std;using namespace Microsoft::VisualStudio::CppUnitTestFramework;int res[10][10];int c[10][10], r[10][10], b[10][10];namespace UnitTest1{TEST_CLASS(UnitTest1){public: int getbox(int x, int y) { int box; if (x >= 1 && x <= 3 && y >= 1 && y <= 3) box = 1; if (x >= 1 && x <= 3 && y >= 4 && y <= 6) box = 2; if (x >= 1 && x <= 3 && y >= 7 && y <= 9) box = 3; if (x >= 4 && x <= 6 && y >= 1 && y <= 3) box = 4; if (x >= 4 && x <= 6 && y >= 4 && y <= 6) box = 5; if (x >= 4 && x <= 6 && y >= 7 && y <= 9) box = 6; if (x >= 7 && x <= 9 && y >= 1 && y <= 3) box = 7; if (x >= 7 && x <= 9 && y >= 4 && y <= 6) box = 8; if (x >= 7 && x <= 9 && y >= 7 && y <= 9) box = 9; return box; } bool check() { memset(c, 0, sizeof(c)); memset(r, 0, sizeof(r)); memset(b, 0, sizeof(b)); for (int i = 1; i <= 9; i++) for (int j = 1; j <= 9; j++) { c[i][res[i][j]]++; r[j][res[i][j]]++; b[getbox(i, j)][res[i][j]]++; } for (int i = 1; i <= 9; i++) for (int j = 1; j <= 9; j++) { if (c[i][j] != 1) return false; if (r[i][j] != 1) return false; if (b[i][j] != 1) return false; } return true; } TEST_METHOD(TestMethod1) { // TODO: 在此输入测试代码 freopen("input.txt", "w", stdout); generator gen(6); int n = 10000; gen.getshudu(n); fclose(stdout); freopen("input.txt", "r", stdin); bool pd = true; for (int i = 1; i <= n; i++) { for (int j = 1; j <= 9; j++) { for (int k = 1; k <= 9; k++) { scanf("%d", &res[j][k]); } } if (!check()) pd = false; } Assert::IsTrue(pd); } TEST_METHOD(TestMethod2) { // TODO: 在此输入测试代码 freopen("input.txt", "w", stdout); generator gen(6); int n = 1000; gen.getshudu(n); fclose(stdout); freopen("input.txt", "r", stdin); bool pd = true; for (int i = 1; i <= n; i++) { for (int j = 1; j <= 9; j++) { for (int k = 1; k <= 9; k++) { scanf("%d", &res[j][k]); } } if (!check()) pd = false; } Assert::IsTrue(pd); }};

}

测试成功的截图

885624-20170910115111882-325424083.png
* * *

psp + 学习进度条更新

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

学习进度条

885624-20170910013149351-1064240602.png


附加题

附加题我只做了第二个部分,除了本来的要有30个空,以及唯一解的需求外,我还满足了第一部分的每个宫至少有两个空格的要求。

代码的命令行运行方式同基础作业

解题思路:

第一种:通过构造数独的程序生成一部分数独当作该程序的输入,先分别对9个宫,每个宫随机挖3个空。再对整体的数独矩阵挖3个空,达到30个。然后用搜索判断这个数独的唯一性。从30个开始可以每多挖一个空判断一次唯一性,从而一个数独就可以生成多个挖空后的数独。这种方法需要大概17秒左右。

第二种:第二种方法是和同学讨论过后才知道的。当一个数独已经具备唯一解,则这个数独少挖一个空也依然是唯一解,所以我们只需要准备一个数独,随机挖出有40个或者更多的空的数独,并且保证具有唯一解。然后我们从这些空中选出一些空去掉,就可得到不同的数独。因为C(40,9)= 273438880 远远超过了1000000。所以很容易就可以得出所有结果。因为满足了每个宫最少有两个空格的需求,所以我需要7秒,如果不需要满足则2秒多就可以了。

下图为代码运行成功的截图

885624-20170910115554913-1867661723.png
* * *

个人总结

这次的作业,加强了我对vs这个工具的使用,知道了如何进行单元测试,如何进行效能分析。虽然还是有很多不懂的地方,但是比一开始什么都不懂好多了。这次的作业如果只算写代码,以及测试的时间并不是很长,但是花在鼓捣vs这个软件上的时间及其漫长,很多东西都是各种百度,到最后却依然不得其解。并且很多文件资料都是英文,应该多加强这方面的阅读能力。

转载于:https://www.cnblogs.com/starset/p/7499999.html

你可能感兴趣的文章
Nginx 笔记与总结(9)rewrite 重写规则
查看>>
SendMessage2
查看>>
变量和运算符
查看>>
IReport中的如何使用变量进行合计
查看>>
snmp简单使用
查看>>
linux操作系统下查看某rpm包是32bit 还是x64bit的命令
查看>>
分布式服务框架 dubbo/dubbox 入门示例
查看>>
Noip2011提高组总结
查看>>
HDU 4416 Good Article Good sentence(后缀自动机)
查看>>
SpringBoot无法书写主启动类的情况之一
查看>>
Java异常之try,catch,finally,throw,throws
查看>>
胡小兔的良心莫队教程:莫队、带修改莫队、树上莫队
查看>>
Java NIO原理及实例
查看>>
Tomcat 多个虚拟主机配置方法
查看>>
android native c 的so调试
查看>>
Strobogrammatic Number
查看>>
实现在手机浏览器上面打 电话发 短信 定位的 功能
查看>>
Number Sequence
查看>>
莫比乌斯反演
查看>>
Java手机游戏开发简明教程 (SunJava开发者认证程序员 郎锐)
查看>>