zoukankan      html  css  js  c++  java
  • 软件工程基础2——数独

    一、 Github项目地址

      https://github.com/fangshuman/sudoku1940

    二、各模块开发上的预估时间

      (见篇末表格)

    三、 解题思路

      刚开始拿到题目的时候,首先看了pdf,因为不知道github是什么就无从下手。大概了解的是这个个人项目分为两个部分,但是经过整个项目的完成之后我觉得这个个人项目可分为四个部分:

      1) 解数独部分

        采用dfs逐个搜索空格,从1~9进行赋值,如果与已知数字不冲突则搜索下一格;如果与已知数字冲突则还原为空格0,并返回上层

      2) 数独终局生成部分

        先定义一行初始行,将初始行进行左移3位和左移6位的操作,可得到数独的前3行

        再将第一行左移1位,得到中3行的第一行,再在此基础上进行左移3位和左移6位的操作,得到数独的中3行

        同理,把第一行左移2位,得到后3行的第一行,再在此基础上进行左移3位和左移6位为操作,得到数独的后3行

        举个例子:

        5  1  2     3  4  6     7  8  9

        3  4  6     7  8  9     5  1  2

        7  8  9     5  1  2     3  4  6

        1  2  3     4  6  7     8  9  5

        4  6  7     8  9  5     1  2  3

        8  9  5     1  2  3     4  6  7

        2  3  4     6  7  8     9  5  1

        6  7  8     9  5  1     2  3  4

        9  5  1     2  3  4     6  7  8

        

        这样的话第一行的数字就可确定整个数独终局。由于第一行第一个数字已经确定,则第一行剩余8个数字可产生的不同排列为8!=40320种

        4,5,6行可进行任意的排列组合,就有6种不同终局,同理7,8,9行也可任意排列组合,又有6种不同终局

        则通过行交换变换得到的有6×6=36种  

        与第一行8个数字不同排列的情况合并,一共有40320×36=1451520种,一定满足1e6的题目条件

      3) 将两部分合并成为完整代码

      4) 上传至github

        有关如何上传到github,百度了好久,也找了好几种方法,特别是标题写了最简便上传github的博客,我最终都失败了,最后找的那个虽然内容很多步骤也很多但至少最后成功了

        参考链接:https://www.cnblogs.com/specter45/p/github.html

    四、设计实现过程

      1) 函数功能

    int main(int argc, char* argv[])  //主函数,获取命令参数,这里主要负责输入和判别功能
    void output();  //输出数独


    /*解数独部分函数*/

    //负责从左上角开始搜索空格,并填入数字,运行过程中利用check判断所填的数字合不合法
    void dfs(int x, int y);  

    //用于判断(x,y)上填写数字a是否符合数独规则,符合返回1,不符合返回0
    int check(int x, int y, int a);  



    /*数独终局生成部分*/
    //负责生成数独板,n为所需的数独终局的局数,运行过程中利用createLine进行行的生成,利用swapLine进行行的交换
    void createBoard(long n);  
    //生成行,通过移位来生成行,属于同一矩阵的移动3位,属于上下相邻矩阵的移动1位,createLine(k)可生成k,k+1,k+2三行
    void createLine(int k);  
    //交换行,通过该函数可将初始图进行更多变换,swapLine(line1,line2)将line1行与line2行交换
    void swapLine(int line1, int line2);  

      2) 解数独部分dfs流程图

      3)单元测试设计

        测试命令行的判定:-s  -c  -a  ab

        运行情况判定:-c 6  -c 1000000  -c 0  -s input文件路径

    五、性能分析

      1) 生成6个数独终局

      2) 生成1000000(1e6)个数独终局

      3) 解12个数独

      4) 解1000个数独

    六、代码说明

      1) 解数独

    //判断填入的数字是否会有冲突
    int check(int x, int y, int a)    
    {
        int i, j;
        for (i = 0; i < 9; i++)    
        {
            if (num[x][i] == a && i != y)    //搜索横排
                return false;
            else if (num[i][y] == a && i != x)    //搜索竖排
                return false;
        }
        int start_x = x / 3 * 3;
        int start_y = y / 3 * 3;
        int end_x = x / 3 * 3 + 2;
        int end_y = y / 3 * 3 + 2;
        for (i = start_x; i <= end_x; i++)    //搜索九宫格
            for (j = start_y; j <= end_y; j++)
                if (num[i][j] == a && i != x && j != y)
                    return false;
        return true;
    }
    
    //dfs搜索填写数字
    void dfs(int x, int y)    
    {
        int i;
        if (y == 9)
        {
            x++;
            y = 0;
        }
        if (x == 9 && y == 0)    //边界
        {
            output();
            flag = true; //如果输出过就不要再继续输出其他解
        }
        if (!num[x][y])
        {
            for (i = 1; i <= 9; i++)
            {
                num[x][y] = i;
                if (check(x, y, i))
                    dfs(x, y + 1);
                if (flag)
                    return;
                num[x][y] = 0;    //还原为空格
            }
        }
        else
            dfs(x, y + 1);
    }

      2) 生成数独终局

    //产生行
    void createLine(int k)
    {
        int i;
        for (i = 0; i < 9; i++)
            num[k][i] = line[i]; //设置第一行
        for (i = 0; i < 6; i++)     //设置第二行
            num[k + 1][i] = line[i + 3];
        for (i = 0; i < 3; i++)
            num[k + 1][i + 6] = line[i];
        for (i = 0; i < 3; i++)
            num[k + 2][i] = line[i + 6]; //设置第三行
        for (i = 0; i < 6; i++)
            num[k + 2][i + 3] = line[i];
    }
    
    //产生数独终局
    void createBoard(long n)
    {
        int i, j, a;
        memset(num, 0, sizeof(0));
        for (a = 0; a < 40320; a++)  //8!=40320,第一行8个数字共8!种排列组合的方式
        {
            for (i = 0; i < 9; i++)    //跳转createLine准备设置前三行
                line[i] = orl[i];
            createLine(0);
    
            for (i = 0; i < 8; i++)    //跳转createLine准备设置中三行
                line[i] = orl[i + 1];
            line[8] = orl[0];
            createLine(3);
    
            for (i = 0; i < 7; i++) //跳转createLine准备设置后三行
                line[i] = orl[i + 2];
            line[7] = orl[0];
            line[8] = orl[1];
            createLine(6);
    
            //完成初始图,4-6行,7-9行可进行交换形成更多新终局
            for (i = 0; i < 2; i++)
            {
                for (j = 0; j < 3; j++)
                {
                    swapLine(i * 3 + 3 + 0, i * 3 + 3 + 1);
                    output();
                    if (--n == 0)
                        break;
                    swapLine(i * 3 + 3 + 1, i * 3 + 3 + 2);
                    output();
                    if (--n == 0)
                        break;
                }
                if (n == 0)
                    break;
            }
    
            if (n == 0)
                break;
            next_permutation(orl + 1, orl + 9);    //重置第一行,共有8!种重置方法
        }
    }
    
    //交换行
    void swapLine(int line1, int line2)
    {
        int tmp[9];
        int i;
        for (i = 0; i < 9; i++)
            tmp[i] = num[line1][i];
        for (i = 0; i < 9; i++)
            num[line1][i] = num[line2][i];
        for (i = 0; i < 9; i++)
            num[line2][i] = tmp[i];
        return;
    }

    七、各模块开发上的实际时间

      (见篇末表格)

    PSP2.1表格

    PSP2.1  

    Personal Software Process Stages    

    预估耗时

    (分钟)

    实际耗时

    (分钟)

    Planning

    计划

    60

    45

    ·Estimate

    ·估计这个任务需要多少时间

    15

    20

    Development

    开发

    1500

    1200

    ·Analysis

    ·需求分析(包括学习新技术)

    100

    220

    ·Design Spec

    ·生成设计文档

    120

    300

    ·Design Review

    ·设计复审

    20

    20

    ·Coding Standard

    ·代码规范

    25

    25

    ·Design

    ·具体设计

    250

    280

    ·Coding

    ·具体编码

    1200

    1320

    ·Code Review

    ·代码复审

    60

    45

    ·Test

    ·测试

    30

    60

    Reporting

    报告

    80

    100

    ·Test Report

    ·测试报告

    30

    15

    ·Size Measurement

    ·计算工作量

    15

    15

    ·Postmortem&Process Improvement Plan

    ·事后总结并提出过程改进计划

    60

    80

     

    合计

    3565

    3745

  • 相关阅读:
    简单播放器(增加sdl事件控制)
    注册表读写
    vb6 的关机代码
    设置系统时间
    获取屏幕工作区、定位任务栏、窗口置顶
    用WINSOCK API实现同步非阻塞方式的网络通讯
    使用API调用外部程序并监控程序状态
    vba截屏保存
    StrConv 内码转换
    阻止文本框获取键盘输入
  • 原文地址:https://www.cnblogs.com/fangshuman/p/8784197.html
Copyright © 2011-2022 走看看