点击获取项目文件

1、对项目的分析与初步计划:

  • 起初拿到这个项目是非常懵逼的,因为涉及到很多个人的知识盲区,诸如:C语言文件的操作、命令行参数、Code Quality Analysis工具、性能分析工具Studio Profiling Tools、GitHub……。可以说在这之前根本就没有接触过这些东西。
  • 虽然什么都不会,但不能什么都不做,于是我制定了以下计划:
    • 什么都不管,先写好代码再说。
    • 翻开《C 程序设计(第四版) 谭浩强》学习C文件的基本操作。
    • 百度了解命令行参数。
    • 其他的太缥缈了,走一步看一步啦。

2、具体实现过程:

  • 根据项目要求,我把代码分成“生成数独终局”和“求解数独残局”两部分。
Creat_ShuDu(argv[]);//生成数独终局 
Solve_shuDu(argv[]);//求解数独残局 
  • 生成数独终局:

    • 对于这一部分,我先生成了一个叫“First line.txt”的文本文件。这个文件用来存储所有可能的数独第一排数据,当需要生成数独终局时,就从这个文件里挑一组数据出来完成数独第一行。(写完这句话我才发现我这不是多此一举吗?!根本没必要啊!)
    • 如何生成一个完成的数独终局,这是一个问题。百度上给了多种方法,考虑到自己的能力,最终选择了暴力回溯法。
      • 对于数独中的每一个小格,它只能填写1~9这9个数字,并且每两个小格间都存在着一定的联系,这给我们的回溯提供了依据。
      • 项目要求生成足够的数独数目。一次性生成多个数独,我可以先写只生成一个数独终局的代码。
      • 从某一小格的某一种可能出发, 搜索从这种情况出发所能达到的所有可能, 当这一条路走到” 尽头 “或者这条路失败的时候, 再倒回到上一步, 从另一个可能出发, 继续搜索. 直到得到足够的终局。
  • 求解数独残局:
    • 其实写完了“生成数独终局”,再写求解部分是非常简单的,因为他们的主要算法都是回溯。唯一的不同就是求解的时候,有些位置已经有了确定的数字。

3、关键代码说明:

  在整个项目代码中最重要的代码当属judge(int i, int j)函数。

int judge(int i, int j)  //搜索第( i , j )位置处可以存储的数字,找到解则返回1,否则返回0
{
     || j > ) ;//搜索结束
    ; k <= ; k++)
    {
        ;                // can 变量用于记录数字k能否放在 ( i , j ) 处
        ; m < i; m++) // 检查同一列是否出现过数字k
        {
            if (shuDu[m][j] == k)  //该列出现过数字k
            {
                can = ;
                break;
            }
        }
        )
        {
            ; n < j; n++) // 检查同一行是否出现过数字k
            {
                if (shuDu[i][n] == k)  //该行出现过数字k
                {
                    can = ;
                    break;
                }
            }
        }
        )                     // 检查在3×3的小方格中是否出现了同一个数字
        {
            ) *  + ; // (i,j)方格所在的3×3小方格i坐标的上限
            ) *  + ;  // (i,j)方格所在的3×3小方格在j坐标的上限

             == ) up1 = i;   //这是针对特殊情况的处理
             == ) up2 = j;

            ; p <= up1; p++)  /* 检查在3×3的小方格中是否出现了同一个数字 */
            {
                ; q <= up2; q++)
                {
                    if (shuDu[p][q] == k)
                    {
                        can = ;
                        break;
                    }
                }
            }
        }
        ) //can==1说明数字k可以放在该位置上
        {
            shuDu[i][j] = k;
            )
            {
                ) == ) ;  /* 到同一行的下一位置开始搜索 */
            }
            else
            {
                )
                {
                    , ) == ) ;   /* 到下一行的第一个空格开始搜索 */
                }
                else
                {
                    num++;
                    if (num<numbers)
                    {
                        Print_shuDu(num);
                    }
                    else
                    {
                        Print_shuDu(num);
                        ;   /* i >= 9  && j >= 9  , 搜索结束 */
                    }
                }
            }
            shuDu[i][j] = ;  /* 关键这一步:找不到解就要回复原状,否则会对下面的搜索造成影响 */
        }
        else continue;//继续尝试其他数字
    }
    ;  /*  1到9都尝试过都不行,则返回递归的上一步 */
}

    这段代码使用的是典型的回溯法。弄懂了这个函数,再写求解数独残局的函数就变的相当简单了。

4、代码优化:

  • 因为我使用的是暴力回溯法,所以能够优化的地方确实不多。我主要优化的是“数独输出函数”。 
void Print_shuDu(int n) //数独输出函数 
    • 起初我通过 fprintf() 函数将数据输出到文件,测试时输出1000000个数独终局需要近2分钟的时间。
    • 后来我将这个函数改成 fputc()的输出方式,运行速度大大加快,对于1000000个数独只需 30左右,缩短了近四分之三的时间。
    • 对此,我特意百度了一下原因。感兴趣的伙伴可以看看。https://blog.csdn.net/slimfox/article/details/1092709

5、后期各种测试:

  • 性能分析如下:

    •   
  • CPU使用率如下:
    •   

6、项目收获:

  • 最大的收获当然是第一次基本独立完成了一个项目,虽然项目很小,做出来的东西很辣鸡。

  • 将该文一开始提到的各种知识盲区大致熟悉了一遍,为以后的学习提供了方便。
  • get到了一些小东西:
    • fputc()比fprintf()快
    • 在VS中scanf要写成scanf_s,为了更安全
    • 在VS中输入一个字符串应写成  scanf_s("%s",s1,sizeof(s1));
    • 在VS中打开一个文件应这样写  fopen_s(&fp, "sudoku.txt", "w");

附:PSP2.1表格

PSP2.1

Personal Software Process

Stages

预估耗时(分钟)  实际耗时(分钟) 
Planning  计划  60 120 
.Estimate  估计这个任务需要多少时间  2000  1500
Development  开发  200 300 
.Analysis  需求分析(包括学习新技术)  30 60 
.Design Spec  生成设计文档  60  40
.Design Review  设计复审(和同事审核设计文档)  60  30
.Coding Standard 代码规范(为目前的开发指定合适的规范)   120  100
.Design  具体设计 60 60 
.Coding  具体编码  200  300
.00Coed Review  代码复审  30 60 
.Test  测试(自我测试,修改代码,提交修改)  60 180 
Reporting  报告  60 120 
.Test Report  测试报告  30 60 
.Size Measurement  计算工作量 30  40 

.Postmortem & Process

Improvement Plan

事后总结,并提出过程改进计划  30  30
           合计    3030  3000

个人项目之数独的生成与数独残局求解——C语言实现的更多相关文章

  1. [2017BUAA软工]第一次个人项目 数独的生成与求解

    零.Github链接 https://github.com/xxr5566833/sudo 一.PSP表格 PSP2.1 Personal Software Process Stages 预估耗时(分 ...

  2. 聊聊 Web 项目二维码生成的最佳姿势

    在设计和实现的过程之后,你永远不知道部署上去的程序会已什么样的姿势运行. 本篇借一次生成二维码逻辑的不同实现,阐述 Web 项目中二维码生成的正确姿势. 文中如有批量,欢迎各位看客老爷拍砖.试运行前5 ...

  3. vue项目通过webpack打包生成的dist文件放到express环境里运行(vue+webpack+express)

    1.首先需要的原料肯定是vue打包生成的dist文件 在vue项目目录下运行:npm run build,等待运行结束,会在项目目录下生成一个dist文件夹,里面会生成一些文件(如下图示) 小的项目文 ...

  4. 在定制工作项时,把“团队项目”作为变量获取生成版本信息

    有用户最近提出这个需求: 通过工作项定制,新增一个字段用以保存项目Bug的"影响版本"信息,但是需要从当前团队项目的服务器生成纪录中获取版本的选项,类似默认模板中的"发现 ...

  5. GNU大型项目构建和覆盖率生成(第一篇)

    目录 0. 序言 1. 项目描述 2. 项目构建 2.1 编译规则 2.2 构建过程 3. 覆盖率分析 0. 序言 在开始正文之前,请允许我先说明一下本文的目的和写作的动机,好让读者不惑. 我们知道, ...

  6. ABP项目中使用Swagger生成动态WebAPI

    本文是根据角落的白板报的<使用ABP实现SwaggerUI,生成动态webapi>一文的学习总结,感谢原文作者角落的白板报. 1 安装Swashbuckle.core 1.1 选择WebA ...

  7. Android Studio] Gradle项目中添加JNI生成文件(.so文件)

    转:http://blog.csdn.net/qiujuer/article/details/24209457 为了适应潮流使用Android Studio还是有半年多了! 对于从Eclipse迁移项 ...

  8. 在VS项目中通过GIT生成版本号作为编译版本号

    上一篇博客写了如何在 .Net 项目使用 SVN 作为版本控制工具时生成与代码对应的组件版本号.虽然在公司一直使用 SVN ,但我却对 GIT 情有独钟(可能要归功于那段捣鼓 ROM 的时光),但少有 ...

  9. 米扑科技的开源项目:sitemap-php 自动生成网站地图

    米扑科技旗下的产品,近期正在做SEO网站优化,其中子需求之一是调研实现了网站地图(sitemap.xml) 封装简化了许多功能模块,现在分享出来,源代码可在Github上下载,有简单的示例. Gith ...

随机推荐

  1. MyBatis动态SQL(二)

    1.foreach foreach语句用来遍历数组和集合对象.标签中的属性: collection属性:值有三种list.array.map open属性:表示调用的sql语句前缀添加的内容 clos ...

  2. du,df区别

    1.记住命令 du:disk Usage -h, --human-readable print sizes in human readable format df:disk free 2.区别 du ...

  3. sql.date

    package com.sxt.utils.date1; import java.sql.Date; /* * sql.date:没有时,分,秒 */ public class TestDate2 { ...

  4. 阿里云亮相2019联通合作伙伴大会,边缘计算等3款云产品助力5G时代产业数字化转型

    4月23日,2019中国联通合作伙伴大会在上海正式开幕,本次大会以“合作不设限,共筑新生态”为主题,涉及5G.边缘计算.云计算.物联网.新媒体.人工智能.互联网化等各领域超过600家合作伙伴与3万名各 ...

  5. jQuery 无刷新评论

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  6. windows环境下安装nodeJS和express,一直提示command not found-配置环境变量

    1.安装NodeJS后,使用npm指令安装express框架,使用 npm install -g express npm install -g express-generator 安装了大半天的时间, ...

  7. Project Euler Problem 15-Lattice paths

    组合数,2n中选n个.向右走有n步,向下走有n步.共2n步.有n步是向右走的,计算向右走的这n步的所有情况,即C(2n,n). 或者,每一步,只能从右边或者上边走过来,只有这两种情况,即step[i] ...

  8. WPF Converter(转)

    WPF Binding 用于数据有效性校验的关卡是它的 ValidationRules 属性,用于数据类型转换的关卡是它的 Converter 属性.下面是实例: 1. Binding 的数据校验 & ...

  9. Python--day71--ORM分组补充

    1,ORM映射对应的sql语句: 2,QuerySet QuerySet方法大全 ########################################################### ...

  10. Python--day66--模板语言之fitler回顾