数独_个人项目

个人项目-数独

Github地址

https://github.com/ZhaoYi1031/Sudoku

花费时间

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

思路描述

第一部分的生成数独,我第一感觉是上学期的学的离散数学3的生成排列与生成组合。比如通过引入逆序来确定唯一的排列给我的启发就是引入二维矩阵的类似逆序的概念来确定可以符合的二维矩阵再进行格式判定;比如反射格雷码法以一个规则不断变化当前01序列,来确定排列。因此我们也可以对一个初始的数独进行变化,比如矩阵的行变换列变换等等。

不过分析之后,我还是选择了最容易想到的方法,回溯按顺序来找出合法的数独。这样的选择是因为不管是随机产生、还是通过矩阵变换或者其它,当需要生成的矩阵数目比较多的时候,可能碰到后期出解的概率减少,而且判重的时间消耗会增加这样的问题。而回溯暴力寻找的好处此时就体现:

  • 不需要判重。因为按顺序找出来的肯定是不同解
  • 时空复杂度相对都不错。而且稳定性好,不会有随机化带来的不均衡问题
  • 编程复杂度低

具体的回溯做法就是从第一行第二列(因为第一行第一列已被填掉)往右来填,来寻找1-9中能填的数字来填到这个方格里。每填一个各自就把该行/列/九宫格的这个数字标记为不可填。每次到行末就调到下一行继续执行。

第二部分求解数独。之前看《挑战程序设计》时看过搜索的剪枝问题就提到了数独,也以前刷poj的时候被一道数独题给卡住,当时那道题网上的标算清一色都是dancing link,用交叉十字循环双向链来做一个精确覆盖。虽然我知道dancing link肯定效率上会比搜索会高,但是这次我却固执地想要通过搜索来解决这次的数独问题。搜索优化的策略自己之前看书的时候有点印象,就是改变搜索的次序。然后自己主要想了想用什么数据结构来存储81个顶点的信息、实现起来会比较好。

优先队列
一开始我想起它的原因是因为每次我们要取出限制最多的点来填,这正好与优先队列这种最小的始终保持在队首的性质是一致的。pass的原因是我每次填完一个点需要对这一列、这一行以及这个九宫格的这20个点进行信息更新,要先取出这些点删掉再插入进去。取的复杂度是O(81)太高。

二叉排序树/平衡二叉树
考虑过c++的set。优缺点基本同priority_queue,扔掉。
考虑过关联容器multimap。key值是限制数,里面存放的是满足限制数等于key的顶点。由于我们每次需要取出限制大的点来填,而按照索引建好之后我们正好可以从key最大的来取。但由于实现起来相对编程复杂度较高,最终我还是选择了用数组来存取。

实现过程

第一部分初始版就是裸的回溯,用了很多的小优化,具体见下一点改进程序性能上。这部分写的时间相对也较短。

主要时间都花在了第二部分的求解数独上。本来按照原来的设计,自己也很快就实现了,但是为了死磕一道OJ题,愣是苦战了3天才调的不超时。每次在本地一测1.2s,1.1s然后被OJ卡一个“Time Limit Exceeded”真是崩溃。当时那三天基本都是下图这种节奏。最终发现当增加了一个小优化后,不再超时了。

一个主要的概念是每个点的限制数。已经填好元素的限制为8(代表只有1个元素可以填) 然后每填一个位置的元素后,我们都去更新该行、该列、该九宫格的其它元素的限制数,如果某一点的限制数达到了8,我们继续更新这个点(这样重复操作就使得我们能够将先期不需要回溯就解决的点全部填掉,避免后期回溯在这些点上浪费时间)

主体的流程图如下:

dfs->modifyElement: 找出限制最大的点
modifyElement->deleteElement: 增加同行/列/九宫格里的点的限制
Note right of dfs: 找不到的时候搜索结束
deleteElement-->modifyElement: 如果有一个点只能填一个值了,填写这个元素

在这里必须提下最后这个从deleteElement指回的这条虚线,这就是我上文提到的那个小优化。之前写的时候我忽视了这一点,但在实际的运行中这是非常有效的。尤其是当0的个数不是很多的时候,我们每次填完一个元素更新的时候都可能在删除时发现另外一个点的限制达到了8,也就是只剩一个元素可以填了,这是我们应当立即来填这个元素。另外,当我们试图填一个元素,却发现不能填的时候,显然这种修改或者说回溯的策略是有问题的,需要我们回溯修改。

单元测试主要包括两部分,是否是合法的数独以及是否与题意是一致的。第二点只有第二部分求解数独有。针对这两个判断我写了如下两个函数,并对第一部分进行了1、10、100、1000、10000的检测数独以及几个参数,第二部分进行了几个不同类型数独的测试。两个主要检测的函数的代码如下:

bool check(int a[M]) {//判断终盘是不是一个数独
    rep(i, 0, 80) {
        a[i] -= ‘0‘;
        if (a[i] < 0 || a[i] > 9)
            return false;
    }
    bool vis_col[N][N], vis_row[N][N], vis_magic[N][N];
    memset(vis_col, false, sizeof(vis_col));
    memset(vis_magic, false, sizeof(vis_magic));
    memset(vis_row, false, sizeof(vis_row));
    int x, y;
    rep(i, 0, 80) {
        x = i / 9;
        y = i % 9;
        if (vis_col[x][a[i]] || vis_row[y][a[i]] || vis_magic[belonging(x, y)][a[i]])
            return false;
        vis_col[x][a[i]] = true;
        vis_row[y][a[i]] = true;
        vis_magic[belonging(x, y)][a[i]] = true;
    }
    return true;
}

bool check2(int a[M], int b[M]) {
    rep(i, 0, 80) {
        if (b[i] > 0 && a[i] != b[i])
            return false;
    }
    return true;
}

测试及代码覆盖率如下图:

改进程序,优化性能

代码1的改进主要在IO的优化上。根据实测,输出的时间速度上,流输出 < fputs < fprintf < fwrite. 另外,在输出的时候,我们要尽可能地拼在一起输出,而不是一个个的数字进行输出。用到的其它的小优化包括:

  1. 用一维数组a[81]取代a[9][9]
  2. 所有的下标从0开始而不是从1开始。这样的优势在于计算相应的行号和列号的时候,直接用pos/9, pos%9就行了,避免了从1开始需要的判断和加法操作
  3. 尽可能减少数组的拷贝,因为回溯需要记录状态而需要拷贝状态,而拷贝数组是一个比较耗时的操作,因此需要减少,在第二部分中最终我只精简到拷贝了那个存放顶点限制数的数组
  4. 尽管将所有数独的输出拼到一个字符数组输出会更节约时间,但是由于这样会牺牲非常大的空间(因为100w的数独大概需要2e8这么大空间)因此最终我还是只是算出一个数独就输出,时间上稍微慢了点(大概在0.5s),但空间上瞬间从1e8下降为1e4的级别
  5. 针对几个使用频繁的简单函数,例如计算属于第几个方格,采用内联函数避免多次编译

在这里我主要举一个我通过性能分析发现的瓶颈并进行改进的例子,发现了STL的string的+操作是一个非常耗时的操作。通过下图可以看到,string的+操作占了1933毫秒。可以说是非常耗时了!

当我们将string改成字符数组直接赋值后,速度立马就上去了,输出的out_file时间只剩下54ms了,如图:

最终的性能分析表如下,输出100万个数独的总时间是1.849秒,可以看到main函数占比都很小了:

代码说明

主要列举部分2的两个主要函数modifyElement和deleteElement来分析说明,其中a[i][j]代表数独中第i位置有没有j的限制,1代表限制即不能填,0代表能填。初始的时候都是0代表每一个位置可以填1~9。两个函数返回true代表可以修改/删除,否则就是和现有的情况矛盾。

bool modifyElement(int pos, int r) {//把pos位置填上r
    int p = pos / 9;//行号
    int q = pos % 9;//列号
    int h;
    x[pos] = r;
    rep(i, 1, 9)
        a[pos][i] = 1;
    a[pos][0] = 8;//限制数为8代表只有r一个值可以填
    a[pos][r] = 0;//除了r可以填其它都标记为不能填
    rep(j, 0, 8) {//同行的元素增加限制
        h = Position(p, j);
        if (h != pos && !deleteElement(h, r))
            return false;
    }
    rep(i, 0, 8) {//同列的元素增加限制
        h = Position(i, q);
        if (h != pos && !deleteElement(h, r))
            return false;
    }
    rep(i, 0, 2)//同九宫格的元素增加限制
    rep(j, 0, 2)
    {
        h = (3 * (p / 3) + i) * 9 + (3 * (q / 3) + j);//简单推导可得
        if (h != pos && !deleteElement(h, r))
            return false;
    }
    return true;
}
bool deleteElement(int pos, int r) {
    int i;
    if (a[pos][r] == 1)//如果这个pos位置不能填i,代表之前已经删除过,直接返回true
        return true;
    a[pos][r] = 1;
    if (++a[pos][0] == 9)//增加了一个限制后,没有可填的元素了,直接返回false
        return false;
    if (a[pos][0] == 8)//优化!某一个点只剩一个元素可以填,那么这个点的值也就固定,我们应当立即去modify这个点的值。
    {
        for (i = 1; i <= 9; ++i)
            if (a[pos][i] == 0)//找到是哪个值可以填
                break;
        if (!modifyElement(pos, i))
            return false;
    }
    return true;
}

GUI

仍在施工中owo.
准备用qt而不是C#

总结

"倔强"地没有选择dancing link而是搜索优化让我在前期的优化性能上耗费了太多时间。以及从mac上习惯的xcode转战到visuo studio也是折腾了好一番(主要Teamviewer远程连着实验室的Windows在操作,有些不方便),因此最后想实现的GUI一直被拖。不过算是自己的一个一周内一直在写的一个小项目吧,希望后面能继续改进一些优化以及单元测试,还有希望能更熟悉一下git的托管(我现在主要还是习惯写好了再一起commit导致基本都是到最后才一起git) 以及虽然现在功能不复杂,还是用类封装一下比较好吧。

路漫漫其修远兮,吾将上下而求索

*:first-child {
margin-top: 0 !important;
}

.markdown-body>*:last-child {
margin-bottom: 0 !important;
}

.markdown-body .anchor {
position: absolute;
top: 0;
bottom: 0;
left: 0;
display: block;
padding-right: 6px;
padding-left: 30px;
margin-left: -30px;
}

.markdown-body .anchor:focus {
outline: none;
}

.markdown-body h1,
.markdown-body h2,
.markdown-body h3,
.markdown-body h4,
.markdown-body h5,
.markdown-body h6 {
position: relative;
margin-top: 1em;
margin-bottom: 16px;
font-weight: bold;
line-height: 1.4;
}

.markdown-body h1 .octicon-link,
.markdown-body h2 .octicon-link,
.markdown-body h3 .octicon-link,
.markdown-body h4 .octicon-link,
.markdown-body h5 .octicon-link,
.markdown-body h6 .octicon-link {
display: none;
color: #000;
vertical-align: middle;
}

.markdown-body h1:hover .anchor,
.markdown-body h2:hover .anchor,
.markdown-body h3:hover .anchor,
.markdown-body h4:hover .anchor,
.markdown-body h5:hover .anchor,
.markdown-body h6:hover .anchor {
height: 1em;
padding-left: 8px;
margin-left: -30px;
line-height: 1;
text-decoration: none;
}

.markdown-body h1:hover .anchor .octicon-link,
.markdown-body h2:hover .anchor .octicon-link,
.markdown-body h3:hover .anchor .octicon-link,
.markdown-body h4:hover .anchor .octicon-link,
.markdown-body h5:hover .anchor .octicon-link,
.markdown-body h6:hover .anchor .octicon-link {
display: inline-block;
}

.markdown-body h1 {
padding-bottom: 0.3em;
font-size: 2.25em;
line-height: 1.2;
border-bottom: 1px solid #eee;
}

.markdown-body h2 {
padding-bottom: 0.3em;
font-size: 1.75em;
line-height: 1.225;
border-bottom: 1px solid #eee;
}

.markdown-body h3 {
font-size: 1.5em;
line-height: 1.43;
}

.markdown-body h4 {
font-size: 1.25em;
}

.markdown-body h5 {
font-size: 1em;
}

.markdown-body h6 {
font-size: 1em;
color: #777;
}

.markdown-body p,
.markdown-body blockquote,
.markdown-body ul,
.markdown-body ol,
.markdown-body dl,
.markdown-body table,
.markdown-body pre {
margin-top: 0;
margin-bottom: 16px;
}

.markdown-body hr {
height: 4px;
padding: 0;
margin: 16px 0;
background-color: #e7e7e7;
border: 0 none;
}

.markdown-body ul,
.markdown-body ol {
padding-left: 2em;
}

.markdown-body ul ul,
.markdown-body ul ol,
.markdown-body ol ol,
.markdown-body ol ul {
margin-top: 0;
margin-bottom: 0;
}

.markdown-body li>p {
margin-top: 16px;
}

.markdown-body dl {
padding: 0;
}

.markdown-body dl dt {
padding: 0;
margin-top: 16px;
font-size: 1em;
font-style: italic;
font-weight: bold;
}

.markdown-body dl dd {
padding: 0 16px;
margin-bottom: 16px;
}

.markdown-body blockquote {
padding: 0 15px;
color: #777;
border-left: 4px solid #ddd;
}

.markdown-body blockquote>:first-child {
margin-top: 0;
}

.markdown-body blockquote>:last-child {
margin-bottom: 0;
}

.markdown-body table {
display: block;
width: 100%;
overflow: auto;
word-break: normal;
word-break: keep-all;
}

.markdown-body table th {
font-weight: bold;
}

.markdown-body table th,
.markdown-body table td {
padding: 6px 13px;
border: 1px solid #ddd;
}

.markdown-body table tr {
background-color: #fff;
border-top: 1px solid #ccc;
}

.markdown-body table tr:nth-child(2n) {
background-color: #f8f8f8;
}

.markdown-body img {
max-width: 100%;
-moz-box-sizing: border-box;
box-sizing: border-box;
}

.markdown-body code {
padding: 0;
padding-top: 0.2em;
padding-bottom: 0.2em;
margin: 0;
font-size: 85%;
background-color: rgba(0,0,0,0.04);
border-radius: 3px;
}

.markdown-body code:before,
.markdown-body code:after {
letter-spacing: -0.2em;
content: "\00a0";
}

.markdown-body pre>code {
padding: 0;
margin: 0;
font-size: 100%;
word-break: normal;
white-space: pre;
background: transparent;
border: 0;
}

.markdown-body .highlight {
margin-bottom: 16px;
}

.markdown-body .highlight pre,
.markdown-body pre {
padding: 16px;
overflow: auto;
font-size: 85%;
line-height: 1.45;
background-color: #f7f7f7;
border-radius: 3px;
}

.markdown-body .highlight pre {
margin-bottom: 0;
word-break: normal;
}

.markdown-body pre {
word-wrap: normal;
}

.markdown-body pre code {
display: inline;
max-width: initial;
padding: 0;
margin: 0;
overflow: initial;
line-height: inherit;
word-wrap: normal;
background-color: transparent;
border: 0;
}

.markdown-body pre code:before,
.markdown-body pre code:after {
content: normal;
}

.markdown-body .highlight {
background: #fff;
}

.markdown-body .highlight .mf,
.markdown-body .highlight .mh,
.markdown-body .highlight .mi,
.markdown-body .highlight .mo,
.markdown-body .highlight .il,
.markdown-body .highlight .m {
color: #945277;
}

.markdown-body .highlight .s,
.markdown-body .highlight .sb,
.markdown-body .highlight .sc,
.markdown-body .highlight .sd,
.markdown-body .highlight .s2,
.markdown-body .highlight .se,
.markdown-body .highlight .sh,
.markdown-body .highlight .si,
.markdown-body .highlight .sx,
.markdown-body .highlight .s1 {
color: #df5000;
}

.markdown-body .highlight .kc,
.markdown-body .highlight .kd,
.markdown-body .highlight .kn,
.markdown-body .highlight .kp,
.markdown-body .highlight .kr,
.markdown-body .highlight .kt,
.markdown-body .highlight .k,
.markdown-body .highlight .o {
font-weight: bold;
}

.markdown-body .highlight .kt {
color: #458;
}

.markdown-body .highlight .c,
.markdown-body .highlight .cm,
.markdown-body .highlight .c1 {
color: #998;
font-style: italic;
}

.markdown-body .highlight .cp,
.markdown-body .highlight .cs {
color: #999;
font-weight: bold;
}

.markdown-body .highlight .cs {
font-style: italic;
}

.markdown-body .highlight .n {
color: #333;
}

.markdown-body .highlight .na,
.markdown-body .highlight .nv,
.markdown-body .highlight .vc,
.markdown-body .highlight .vg,
.markdown-body .highlight .vi {
color: #008080;
}

.markdown-body .highlight .nb {
color: #0086B3;
}

.markdown-body .highlight .nc {
color: #458;
font-weight: bold;
}

.markdown-body .highlight .no {
color: #094e99;
}

.markdown-body .highlight .ni {
color: #800080;
}

.markdown-body .highlight .ne {
color: #990000;
font-weight: bold;
}

.markdown-body .highlight .nf {
color: #945277;
font-weight: bold;
}

.markdown-body .highlight .nn {
color: #555;
}

.markdown-body .highlight .nt {
color: #000080;
}

.markdown-body .highlight .err {
color: #a61717;
background-color: #e3d2d2;
}

.markdown-body .highlight .gd {
color: #000;
background-color: #fdd;
}

.markdown-body .highlight .gd .x {
color: #000;
background-color: #faa;
}

.markdown-body .highlight .ge {
font-style: italic;
}

.markdown-body .highlight .gr {
color: #aa0000;
}

.markdown-body .highlight .gh {
color: #999;
}

.markdown-body .highlight .gi {
color: #000;
background-color: #dfd;
}

.markdown-body .highlight .gi .x {
color: #000;
background-color: #afa;
}

.markdown-body .highlight .go {
color: #888;
}

.markdown-body .highlight .gp {
color: #555;
}

.markdown-body .highlight .gs {
font-weight: bold;
}

.markdown-body .highlight .gu {
color: #800080;
font-weight: bold;
}

.markdown-body .highlight .gt {
color: #aa0000;
}

.markdown-body .highlight .ow {
font-weight: bold;
}

.markdown-body .highlight .w {
color: #bbb;
}

.markdown-body .highlight .sr {
color: #017936;
}

.markdown-body .highlight .ss {
color: #8b467f;
}

.markdown-body .highlight .bp {
color: #999;
}

.markdown-body .highlight .gc {
color: #999;
background-color: #EAF2F5;
}

.markdown-body .octicon {
font: normal normal 16px octicons-anchor;
line-height: 1;
display: inline-block;
text-decoration: none;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}

.markdown-body .octicon-link:before {
content: ‘\f05c‘;
}

.markdown-body .task-list-item {
list-style-type: none;
}

.markdown-body .task-list-item+.task-list-item {
margin-top: 3px;
}

.markdown-body .task-list-item input {
float: left;
margin: 0.3em 0 0.25em -1.6em;
vertical-align: middle;
}

/*

github.com style (c) Vasily Polovnyov

*/

.hljs {
display: block;
overflow-x: auto;
padding: 0.5em;
color: #333;
background: #f8f8f8;
-webkit-text-size-adjust: none;
}

.hljs-comment,
.diff .hljs-header {
color: #998;
font-style: italic;
}

.hljs-keyword,
.css .rule .hljs-keyword,
.hljs-winutils,
.nginx .hljs-title,
.hljs-subst,
.hljs-request,
.hljs-status {
color: #333;
font-weight: bold;
}

.hljs-number,
.hljs-hexcolor,
.ruby .hljs-constant {
color: #008080;
}

.hljs-string,
.hljs-tag .hljs-value,
.hljs-doctag,
.tex .hljs-formula {
color: #d14;
}

.hljs-title,
.hljs-id,
.scss .hljs-preprocessor {
color: #900;
font-weight: bold;
}

.hljs-list .hljs-keyword,
.hljs-subst {
font-weight: normal;
}

.hljs-class .hljs-title,
.hljs-type,
.vhdl .hljs-literal,
.tex .hljs-command {
color: #458;
font-weight: bold;
}

.hljs-tag,
.hljs-tag .hljs-title,
.hljs-rule .hljs-property,
.django .hljs-tag .hljs-keyword {
color: #000080;
font-weight: normal;
}

.hljs-attribute,
.hljs-variable,
.lisp .hljs-body,
.hljs-name {
color: #008080;
}

.hljs-regexp {
color: #009926;
}

.hljs-symbol,
.ruby .hljs-symbol .hljs-string,
.lisp .hljs-keyword,
.clojure .hljs-keyword,
.scheme .hljs-keyword,
.tex .hljs-special,
.hljs-prompt {
color: #990073;
}

.hljs-built_in {
color: #0086b3;
}

.hljs-preprocessor,
.hljs-pragma,
.hljs-pi,
.hljs-doctype,
.hljs-shebang,
.hljs-cdata {
color: #999;
font-weight: bold;
}

.hljs-deletion {
background: #fdd;
}

.hljs-addition {
background: #dfd;
}

.diff .hljs-change {
background: #0086b3;
}

.hljs-chunk {
color: #aaa;
}
-->

时间: 2024-10-03 07:22:57

数独_个人项目的相关文章

数独GUI程序项目实现

数独GUI程序项目实现 导语:最近玩上了数独这个游戏,但是找到的几个PC端数独游戏都有点老了...我就想自己做一个数独小游戏,也是一个不错的选择. 前期我在网上简单地查看了一些数独游戏的界面,代码.好好地了解了一下现在数独游戏的大概的框架.当然,我自己写的小游戏,也许没那么好.但是我一定会一点点升级这个小游戏的. 目前,我做的游戏是V1.0版本的,只能说实现了这个游戏的基本功能:可以进行数独游戏.可以更换背景色以及一些其他的基本功能.接下来,在空余时间,我会进行对其中一Studying功能的实现

C#_.NetCore_WebAPI项目_EXCEL数据导出(ExcelHelper_第二版_优化逻辑)

原文:C#_.NetCore_WebAPI项目_EXCEL数据导出(ExcelHelper_第二版_优化逻辑) 项目需要引用NPOI的Nuget包:DotNetCore.NPOI-v1.2.2 本篇文章是对WebAPI项目使用NPOI操作Excel时的帮助类:ExcelHelper的改进优化做下记录: 备注:下面的帮助类代码使用的文件格式为:xlsx文件,xlsx相对xls的优缺点代码里有注释,推荐使用xlsx文件保存数据! using Microsoft.AspNetCore.Mvc; usi

软工_结对项目总结博客

关于结对编程 第一次进行真正的结对编程,而且我们组又是最奇葩的三人组合(14061183韩青长)(14061195陈彦吉),在经历了三天的合作以后,感觉收获还是蛮多的,下面是我对于结对编程的一些个人体验. 优点 在结对编程的过程中,两个人共同面对同一份代码,编码时旁边时刻有人提示监督.这样写出的代码,首先考虑的特殊情况会更多,能避免很多一个人编程时因为考虑不周而在某个不起眼的地方产生的Bug,代码质量更高,少了很多调试时间. 同时,由于两个人交替工作,一方面可以缓解疲劳,同时又因为身旁有人共同工

团队开发_软件项目风险管理

一.说明 软件项目的风险管理是对软件项目的预测和估计,在一定程度上影响着软件的开发进度和完成的效果.因此, 软件的风险管理是特别重要的,以下是我们小组讨论之后,对团队开发的项目的软件风险的估计. 二.软件风险表 编号 风险名称 发生概率 损失(人/两天) 危险度(两天) 1 计划过于乐观,没有在规定的时间内完成spring计划的要求 60 3 1.8 2 设计欠佳,需要重新设计界面 30 2 0.6 3 由于个别成员临时有事,导致在其工作无法进行,从而影响项目的进度 30 4 1.2 4 在软件

龙威零式_团队项目例会记录_2

有图有真相 会议议程: 任务回顾: 首先昨天布置的任务大家都已经陆陆续续开始做了,只是苦于整体的框架还并不清晰 所以没有什么突破性的进展 明日安排: 今天在项目方面我们终于拿到了服务器的相关数据,所以明天大家所有人除了继续完成昨天遗留的任务之外,每个人都要登录服务器并且先熟悉一下代码,并且进行分工阅读代码. 大家普遍对之后的任务有较高的期待 大家加油

北京地铁_结对项目_附加题

地铁出行项目(续)- 附加题 团队成员:杨金键 谢振威 金豪 要求描述: 使程序支持不同城市的地图.请让程序能处理上海的地铁地图,或者其它城市的地图.把程序由 “固定处理一个地图” 升级为 “能处理多个地图”, 程序的什么模块需要变化? 其实,在我们设计程序之初就已经考虑到了程序将来的可扩展性,所以无论是地图储存文件还是代码我们都是从这个角度出发考虑的. 具体来说: 取消所有对于北京地图的特殊化处理,针对特殊的地方,例如环线或者单行线则定义关键词统一处理 所有地图相关信息都靠文件读取,避免地图相

软工_个人项目总结博客

项目预先规划 在个人项目开始之前,我之前的编程几乎从来没有在开始前预估过时间,所以也就是摸着石头过河,大概根据之前的经验估计了一下时间. 预估时间(单位均为小时) PSP 2.1 Personal Software Process Stages Time Planning 计划 · Estimate · 估计这个任务需要多少时间 0.1 Development 开发 · Analysis · 需求分析 (包括学习新技术) 1 · Design Spec · 生成设计文档 0.5 · Design

现代软件工程_团队项目_阿尔法阶段_第二次会议记录_2017.11.13

第二次会议记录 会议时间:2017.11.13  12:00-12::30 会议地点:中科大西区第三教学楼A教一楼讨论区 参会人员:刘荪傲 姜博文 顾培健 徐宇飞 张淦霖 [内容一]:页面原型v1.0展示 (一)介绍 经过对比,我们采用了mockplus做页面原型设计软件.于11月12日设计出了v1.0版本. 版本结构如下: v1.0 1.0.0 登录 1.0.1 创建新用户 1.0.2 找回密码 1.0.3 已有自习列表 1.0.4 发布我的自习 1.0.5 我已完成的自习 1.0.6 该自习

现代软件工程_团队项目_阿尔法阶段_需求分析文档_2017.11.13

用户需求分析 版本 v1.0.0 0.目录 1. 引言 1.1 编写目的1.2 项目背景1.3 预期的读者和阅读建议1.4 项目范围1.5 参考资料 2.用户需求分析 2.1. 调查问卷(User Survey) 2.2. 用户场景分析(User Analysis) 用户场景用户需求 2.3. 项目创新点与收益(Approach and Benefit) 创新点收益 2.4. 市场与竞争(Competitors) 市场分析竞争 1. 引言 1.1 编写目的 此需求规格说明书编制目的是明确本项目的