说明


解题思路

  • 一开始拿到的时候,有一个思路,可以先填写全盘的“1”,然后在插空填满全盘的“2”。后来觉得自己理不清那个思路。遂放弃。

    参考思路:(http://blog.csdn.net/nibiewuxuanze/article/details/47679927)
  • 第二个思路,是在一个博客上看到的,博主是把第一行随机打散然后第二行开始,从1-9测试哪一个数能填入此空,继续往下。但是这个思路是有问题的,因为选择填入的数字是一个循环,从1-9,也就是就是一旦第一行确定了,下面的数独只有一个唯一解了,重复率极高。
  • 后来改进了,通过rand( )函数随机生成数字然后测试能否填入该空格。测试条件三个:行、列、3x3小方格。
  • 为了随机性更强,又改进了一种方式:每次都随机打乱一个初始数组,然后从这个数组里抽选数字考虑是否填入。
random_shuffle(&(vi[1]), &(vi[10]));//vi一维数组打乱1-9
  • 对于左上角固定数字的思路,一开始是打算等数独终盘生成后,找到第一个3x3方格里的需要的数字,把该行该列换到第一个。后来觉得这种方法花费的时间很多,修改成了一开始就固定sudoku[1][1]=x。从第二个数开始填写,加快了运行速度,缩短时间。

    参考思路:(http://blog.jobbole.com/108488/?utm_source=tuicool&utm_medium=referral)

    注意:
  • 第一行除了第一个固定,其他地方都通过find(i,j)取得k值
  • 在选取k值的时候,用一个数组先打乱,再按序从中选取

关键代码

  • 除了主函数外只有两个函数

    bool isNUM(string str)//用于判断输入的是否是纯数字

    bool find(int i, int j)//搜索(i,j)可以存储的数字

    几乎把所有功能都堆在了find(i,j)……发现后面的分析等等很不好做,下一次会注意书写的时候把不同功能拆开,模块化处理。

  • Bool型函数,返回true or false,用sign标识简单明白体现是否能放在某个位置

  • 每次都随机打散数组vi,从随机数组vi中循环挑选数字填写,然后三个判断条件:这一行是否有这个数字、这一列是否有这个数字、这一个3x3小矩阵是否有这个数字。如果都符合,就继续find下一个位置能填入的数字。如果1-9全部尝试了都不符合,就退回上一步。

bool find(int i, int j)//搜索(i,j)可以存储的数字
{
int vi[10];
for (int i1 = 1; i1 <= 9; ++i1)
vi[i1] = i1;
random_shuffle(&(vi[1]), &(vi[10]));//vi一维数组打乱1-9 for (int s = 1; s <= 9; s++)//循环数组取数字
{
int k = vi[s];//取k为数组中第一位数
bool sign = true;//sign标记能否将k放在(i,j)处 for (int m = 1; m < i; m++)
if (sudoku[m][j] == k)//检查同一列是否出现过数字k
{
sign = false;
break;
} if (sign == true)
{
for (int n = 1; n < j; n++)
if (sudoku[i][n] == k)//检查同一行是否出现过数字k
{
sign = false;
break;
} } if (sign == true)
{
int imax = (i / 3) * 3 + 3;//(i,j)所在的3x3小方格的最大行数
int jmax = (j / 3) * 3 + 3;//(i,j)所在的3x3小方格的最大列数 if (i % 3 == 0)
imax = i;
if (j % 3 == 0)
jmax = j; for (int p = imax - 2; p <= imax; p++)//检查3x3小方格
{
if (sign == false)
break; for (int q = jmax - 2; q <= jmax; q++)
if (sudoku[p][q] == k)
{
sign = false;
break;
}
}
} if (sign == true)
{
sudoku[i][j] = k;
if (j < 9)
{
if (find(i, j + 1) == true)//搜索本行右边的位置
return true;
}
else
{
if (i < 9)
{
if (find(i + 1, 1) == true)//搜索下一行
return true;
}
else
return true;//i>=9,j>=9,搜索结束 }
sudoku[i][j] = 0;//找不到要清0
}
}
return false;//本位置1-9都不能填,返回上一步
}

测试运行

  • 错误指令/结果

    sudoku.exe -o 1

    Sudoku.exe -c abc

    Sudoku.exe -c 0

  • 正确结果

    Sudoku.exe -c 3



  • (9.10更新)发现还要考虑如果传入的参数不等于3个的情况

    sudoku.exe -c -c 1

ps:后来发现改成Release的状态下运行速度更快,但是之前测试的版本是Debug的,所以上述的截图上在Debug的文件夹下。


效能分析与改进

  • n=1000000
  • 解决了大部分的奇奇怪怪的输入输出问题,但是1000000的运行时间还是太久,需要15分钟左右,但是没有想到更好更快的改进方法。并且没有进行重复判断,完全是依赖随机性来避免重复。
  • (9.10更新)修改了输出之后,不用ofstream类,用输出重定向,数独缩短了将近一半,现在只需要497s,在十分钟以内。
  • (再更新)一开始没有把编译的版本改为Release,所以跑的非常慢,多达857s,超出十分钟。后来优化了一点点的代码,达到497s。将版本改为release之后,速度达到63s。

(舍友的电脑左下角会显示函数名但是我的全都是工程的名字……不知道为什么……)





  • 本次作业,自己的代码不够模块化,所有的东西都往一个函数里放,好像这个功能很强大似得。但是其实后面效能分析的时候就比较不容易改进,所以下次码代码的时候,要分块分清楚,更加规范。这次由于在修改输入输出的一些问题花费了很多时间,遂没有去修改函数方面的问题。

    命令行执行EXE参考材料:(http://blog.csdn.net/txl199106/article/details/44703489)

PSP表格

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

遇到的困难及解决方法

- 困难描述

1.遇到的最大的困难就是太久没有接触代码了,一开始的时候,简直无从下手,从书柜里翻出了c语言和c++的书,稍微翻了一下,看了几眼头文件什么的。而且,很久没有打代码,思路很混乱,很难切入这个问题,想到核心,进入状态需要很久。

2.二是不熟悉VS。安装花了很长时间在捣鼓,然后关于新建的东西也比较不熟悉,后来是向同学请教了之后才明白具体如何新建。不然之前一直在报错“找不到EXE文件”,搜遍了百度都没法解决……原来是新建的时候建错了文件。并且,对于测试等等,也是第一次接触,一头雾水。一些名词,比如“代码覆盖率”等等都是第一次听说,感觉高大上了不少……

3.对于命令行运行EXE也是第一次接触,花了很多时间看相关的知识,修改主函数。

4.对于单元覆盖率、单元测试还是不熟悉。比起一些大一就用过Github的同学而且我完全是纯新手……一开始有点茫然

- 做过哪些尝试

1.看其他同学写的博客,有的同学会写教程,感觉很赞,比如VS安装教程等等,虽然可能大部分人都会但是……对于比较菜鸟的我还是挺有用的T T。。

2.还有的同学会把觉得不错的教程链接贴出来,我就进去看看,感觉有的写得简单易懂,能一下子理解很多。

3.感觉现在的自己还处于“拿轮子造车”的阶段,还有很多东西不是真正属于自己的,还需努力。

- 有何收获

1.熟悉了对于命令行运行exe的主函数写法,文件的输出,输出重定向,最重要的是重新拾起了打代码的思维。

2.本次的习题,我觉得和之前上c++的作业还是有很大区别的,因为c++只需要打一个代码就好了,而本次作业,就更接近真正的程序员要做的事了,包括各种测试等等,完成度更高,更完善了,更像是一个项目而不是一段代码了。

软工实践第二次作业-sudoku的更多相关文章

  1. 软工实践第二次作业—Wordcount

    Git仓库地址:https://github.com/cwabc/PersonProject-C 一.问题描述 输入一个txt文件名,以命令行参数传入,程序能够统计txt文件中的以下几个指标: 统计文 ...

  2. 软工实践 - 第二十九次作业 Beta 冲刺(7/7)

    队名:起床一起肝活队 组长博客:https://www.cnblogs.com/dawnduck/p/10159251.html 作业博客:[班级博客本次作业的链接] (https://edu.cnb ...

  3. 软工实践 - 第二十一次作业 BETA 版冲刺前准备

    软工 · BETA 版冲刺前准备(团队) 过去存在的问题 组员之间缺乏沟通,前后端缺乏沟通协作 组员积极性不高 基础知识不够扎实 手动整合代码效率过低 我们已经做了哪些调整/改进 通过会议加强组员之间 ...

  4. 软工实践 - 第二十八次作业 Beta 冲刺(6/7)

    队名:起床一起肝活队 组长博客:https://www.cnblogs.com/dawnduck/p/10146478.html 作业博客:班级博客本次作业的链接 组员情况 组员1(队长):白晨曦 过 ...

  5. 软工实践 - 第二十七次作业 Beta 冲刺(5/7)

    队名:起床一起肝活队 组长博客:https://www.cnblogs.com/dawnduck/p/10134471.html 作业博客:班级博客本次作业的链接 组员情况 组员1(队长):白晨曦 过 ...

  6. 软工实践 - 第二十六次作业 Beta 冲刺(4/7)

    队名:起床一起肝活队 组长博客:https://www.cnblogs.com/dawnduck/p/10124816.html 作业博客:班级博客本次作业的链接 组员情况 组员1(队长):白晨曦 过 ...

  7. 软工实践 - 第二十五次作业 Beta 冲刺(3/7)

    队名:起床一起肝活队 组长博客:https://www.cnblogs.com/dawnduck/p/10116979.html 作业博客:班级博客本次作业的链接 组员情况 组员1(队长):白晨曦 过 ...

  8. 软工实践 - 第二十四次作业 Beta 冲刺(2/7)

    队名:起床一起肝活队 组长博客:https://www.cnblogs.com/dawnduck/p/10105380.html 作业博客:班级博客本次作业的链接 组员情况 组员1(队长):白晨曦 过 ...

  9. 软工实践 - 第二十三次作业 Beta 冲刺(1/7)

    队名:起床一起肝活队 组长博客:https://www.cnblogs.com/dawnduck/p/10093337.html 作业博客:班级博客本次作业的链接 组员情况 组员1(队长):白晨曦 过 ...

随机推荐

  1. Ubuntu14.04 编译 Android 5.1.1源码(采用国内镜像)

    欢迎转载,转载请注明出处: http://www.cnblogs.com/lanrenxinxin/p/5424554.html 之前就有编译android源码的想法,但是由于有GFW的存在,又没有梯 ...

  2. FC游戏 《三国志2-霸王的大陆》攻略

    <三国志2-霸王的大陆>是日本南梦宫公司研发的一款历史战略模拟游戏,于1992年06月10日在红白机平台上发行. 在开始游戏选择君主时(一定要在君主未出现前的画面时进行第二步),按住1P的 ...

  3. MVC和WebForm区别

    WebForm的理解 1. WebForm概念 ASP.NETWebform提供了一个类似于Winform的事件响应GUI模型(event-drivenGUI),隐藏了HTTP.HTML.JavaSc ...

  4. 正则检查是否为IP地址

    /// <summary> /// 是否为ip /// </summary> /// <param name="ip"></param&g ...

  5. 在 浏览器中调用外接设备— —手写板 【win10 x64 手动注册ocx控件的方法】

    PPAXSignToolSDK.ocx 浏览器下使用手写板时调用的控件,使用前必须先注册,,不然浏览器下版本无法正常工作. ocx 控件在安装包运行时会自动注册,如果安装包没有注册成功,需要进行手动注 ...

  6. Java并发编程:Java创建线程的三种方式

    目录 引言 创建线程的三种方式 一.继承Thread类 二.实现Runnable接口 三.使用Callable和Future创建线程 三种方式的对比 引言 在日常开发工作中,多线程开发可以说是必备技能 ...

  7. web新手——新闻列表这样写不容易出错

    1.先写结构 a.如果列表没有时间   结构为:<li><a>新闻内容</a></li> b.如果列表有时间      结构为:<li>&l ...

  8. Docker 加速器设置

    在部署完docker的时候我们需要进行在镜像源下载镜像的时候有时候会出现特别慢的情况(这是因为本地到源的网络出现了问题),这时候就需要使用加速器来对镜像进行下载了,在面咱们就聊一聊docker加速器的 ...

  9. 浅谈Java多线程同步机制之同步块(方法)——synchronized

    在多线程访问的时候,同一时刻只能有一个线程能够用 synchronized 修饰的方法或者代码块,解决了资源共享.下面代码示意三个窗口购5张火车票: package com.jikexueyuan.t ...

  10. (后台)org.apache.catalina.connector.ClientAbortException: null

    比如错误日志是这样的: org.apache.catalina.connector.ClientAbortException: null 那么问题基本上就是服务器准备进行response的时候,发现连 ...