[2017BUAA软工]我的项目

软工我的项目git



1、Github项目地址

https://github.com/Lydia-yang/2017BUAA-SoftwareEngineeringgithub


2、解题思路

在刚开始拿到题目的时候,关于生成数独终局,个人思路是能够随机生成数而后选择适合的数填满便可获得,后来经过上网查找一些数独生成算法,发现能够经过必定的顺序来减小工做量,好比将1到9个数字依次随机填入3*3的宫格里,或者记录每次每次尝试的数避免重复,还有初始化对角线的3个3*3的宫格,或者依次填入1到9等。最后选定了将1到9个数值依次填入3*3的宫格里这种算法,也就是这篇博客的算法。
将数独分为9小块,将1-9按照必定序列填写1-9小块,好比先将1填入1号小块,再填入2号小块,知道填完9号小块,再填2与1同样,遍历全部数便可获得一个生成数独。
至于解数独,思路与生成数独差很少,也是回溯,可是是对于每个没有填的位置试全部可能的数字。算法


3、设计实现过程

实现个人算法,首先,要有一个存储九宫格的二位数组,出于考虑,我建立了一个数独类,这个类里有相应的行列及3*3小块的重复检查,以及插入和删除,因为我解决数独和生产数独用的是不一样的方法来插入数字的(一个是肯定数字选位置,一个肯定位置选数字),因此有两种插入的方法,而后就是打印数独的方法。
在处理命令行中,有判断-c后面接的是不是正整数的函数,一样,生成数独和解数独都有各自的函数,解数独是经过文件读入的,所以也设定了一个处理文件读入函数,在后面优化的过程当中,又新增了输出到文件的函数,单元测试主要是将produce和solve这两个函数测试了一遍。下图是函数类之间的关系:数组


4、性能改进

一开始生成数独时,几分钟都没出结果,后来通过性能分析,以下图:
函数


发现是输出占了大多数时间,后来作了优化,将输出结果先输出到一个字符数组里,再所有一块儿输出,最后的性能分析以下:
post


5、代码说明

下面这段代码是用来解数独的,其中输入表明的含义为:性能

  • sudoku sudo, 存储待解的数独
  • int x[], 全部为空位置的x值
  • int y[], 全部为空位置的y值
  • int total, 空位子的总数
  • int & count, 用来记录目前已经填了多少空位子
  • char *str, 字符数组用来储存须要打印的数独
  • int &count_s, 用来标记字符数组的元素个数

对于每一次执行,将这个空位子插入数字,并标记已经试过的数字,最后完成时输出,每次回溯时都清空当前位置。单元测试

void solve(sudoku sudo, int x[], int y[],int total, int & count, char *str, int &count_s) {
    int marked[9] = { 0 };//用来标记数字是否已经选过
    int new_count = count;
    while (true) {

        int now = sudo.insert(1, x[new_count], y[new_count], marked);//在空位子插入数字

        if (now < 0) return;
        else marked[now-1] = 1;

        if (new_count == total - 1) {//最后一个
            sudo.printsudoku(str, count_s);//打印数独
            return;
        }
        count = new_count + 1;
        solve(sudo, x, y, total, count, str, count_s);//下一个
        if (count == total - 1) return;
        sudo.del(1, x[new_count], y[new_count]);
    }
    
}



下面这段代码是用来生成数独的,其中输入表明的含义为:测试

  • int total, 最终须要生成数独的总个数
  • int nums[], 1-9的序列用来规定遍历数的顺序
  • int block_num, 标记当前的3*3的块号
  • int & count_total, 用来标记当前已经生成的数独个数
  • int count_nums, 用来标记当前对于nums的元素位置
  • sudoku s, 当前已经填好一些空的数独
  • char *str, 字符数组用来储存须要打印的数独
  • int &count_s, 用来标记字符数组的元素个数

对于每一次执行,将这个数字插入当前3*3小块空的位置,并标记已经试过的位置,最后完成时输出,每次回溯时都清空当前位置。优化

void produce(int total, int nums[], int block_num, int & count_total, int count_nums, sudoku s, char *str, int &count_s) {
    int marked[9] = { 0 };//标记已经试过的位置
    int new_block_num, new_count_nums;
    
    while (true) {
        new_block_num = block_num + 1;
        new_count_nums = count_nums;
    
        int now = s.insert(nums[new_count_nums], new_block_num, marked);
    
        if (now <0) return;
        else marked[now] = 1;

        if (new_block_num == 9) {
            if (new_count_nums < 8) {
                new_count_nums=count_nums+1;
                new_block_num = 0;
            }
            else {//填写至最后一个
                count_total++;
                s.printsudoku(str, count_s);//打印数独
                s.del(0, new_block_num, now);
                return;
            }
        }
        produce(total, nums, new_block_num, count_total, new_count_nums, s, str, count_s);
        if (count_total == total) return;
        s.del(0, new_block_num, now);
    }
}


6、PSP

Psp personal software progress stages 预估耗时 实际耗时
planning 计划 20 30
estimate 估计这个任务须要多少时间 10 10
development 开发 480 600
analysis 需求分析 10 10
design spec 生成设计文档 30 35
design review 设计复审 0 0
coding standard 代码规范 10 15
design 具体设计 60 70
coding 具体编码 240 300
code review 代码复审 120 130
test 测试 240 300
reporting 报告 20 18
test report 测试报告 20 10
size measuring 计算工做量 5 3
postmortem & process improvement plan 过后总结,提出过程改进计划 20 20
合计 1285 1551
相关文章
相关标签/搜索