第二次作业——个人项目实战:数独
运行环境: windows10
编程IDE: Visual Studio 2017 社区版
编程语言: C++
Github地址:传送门
1)项目需求
利用程序随机构造出N个已解答的数独棋盘。
输入: 数独棋盘题目个数N(0< N<=1000000)
输出:随机生成N个 不重复 的 已解答完毕的 数独棋盘,并输出到sudoku.txt中
2)解题思路
首先我想到的是本题中的随机性,用C++中的随机函数rand()来产生随机数。在一开始先利用随机数生成左上角的第一个宫格,在此过程中只需要判断第一个宫格是否数独冲突。在接下去的宫格生成过程中,需要每个数的宫格检查、行检查、列检查。而在后续的宫格生成过程中可能会存在无解的情况,这时候就需要回溯重来。
由于左上第一个数字是固定的,则第一个宫格的随机排列组合有8!=40320种,若再加上其他行列的变化后会有几何数级增长的可能性,经过了解,数独的可能有6,670,903,752,021,072,936,960种组合。其他宫格中每个数字的生成有9种可能(1~9),若试完这些可能仍然无法填入宫格则为无解,需要重新再来。
3)设计实现
采用一个动态的二维数组来表示数独棋盘(9×9),初始化为0表示未填入。设计列检查、行检查、宫检查的函数以及生成宫格的函数和打印函数(检查用)。输入需要生成棋盘的个数N后,开始初始化棋盘,首先用随机数生成一个满足要求的第一宫格,接下去的八个宫格均同样方法(若无解回到第一步生成宫格开始),为提高效率,若重试次数过多(这里限制为100次),则重新生成整个棋盘。(简单粗暴的方法)
4)代码说明
//行检查(列检查同理)
bool Sudoku_Row(int arr[9][9],int row, int num)
{
bool flag = false;
for (int i = 0; i < 9; i++)
{
if (arr[row][i] == num)
{
flag = true;
break;
}
}
return flag;
}
//宫检查
bool Sudoku_Square(int arr[9][9],int row, int col, int num)
{
bool flag = false; //冲突标志
int Square_Row = (row / 3) * 3;
int Square_Col = (col / 3) * 3;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
if (arr[Square_Row + i][Square_Col + j] == num)
{
flag = true;
break;
}
}
}
return flag;
}
//生成宫格
bool makeSquare(int arr[9][9],int num)
{
int square_row = (num / 3) * 3;
int square_col = (num % 3) * 3;
int x, y;
int temp;
if (num == 0) //第一个宫格
{
for (int i = 1; i < 9; i++)
{
x = square_row + i / 3;
y = square_col + i % 3;
temp = Random(8) + 2;//生成2~9的随机数
if (!Sudoku_Square(arr, x, y, temp))
{
arr[x][y] = temp;
}
else i--;
}
}
else //其他宫格
{
int try_count = 0;
temp = Random(9)+1;////生成1~9的随机数
for (int i = 0; i < 9; i++)
{
x = square_row + i / 3;
y = square_col + i % 3;
temp++;
temp = temp % 10;//循环随机数在1~9范围内
if (!Sudoku_Square(arr, x, y, temp) && !Sudoku_Col(arr, y, temp) && !Sudoku_Row(arr, x, temp)&&temp!=0)
{
arr[x][y] = temp;
try_count = 0;
}
else
{
i--;
try_count++;
}
if (try_count > 10)
{
return false;
break;
}//若所有可能试完则返回无解
}
}
return true;//有解
}
5)测试运行
N=10000
如图所示 输出和宫格生成占用的时间最多,在这方面还有很多需要改善。
由于项目开始时间太晚,只能先完成这些部分了,后续再完善(有生之年)
6)关于执行力与泛泛而谈
执行力是一个种将意愿转化为实际结果的能力,也就是与办事能力、工作效率相挂钩。若是三分钟热度,往往只是停留在空想阶段,容易泛泛而谈,一旦碰壁就放弃。兴趣和热情很重要,方式方法也是另一面手心,热情毕竟是有限的,提高执行力能看到实际的结果,也比较有信心把这件事做下去。
PSP
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 600 | 800 |
· Estimate | · 估计这个任务需要多少时间 | 30 | 20 |
Development | 开发 | 600 | 800 |
· Analysis | · 需求分析 (包括学习新技术) | 120 | 60 |
· Design Spec | · 生成设计文档 | 100 | 60 |
· Design Review | · 设计复审 (和同事审核设计文档) | 60 | 30 |
· Coding Standard | · 代码规范 (为目前的开发制定合适的规范) | 100 | 0 |
· Design | · 具体设计 | 100 | 100 |
· Coding | · 具体编码 | 600 | 800 |
· Code Review | · 代码复审 | 100 | 150 |
· Test | · 测试(自我测试,修改代码,提交修改) | 100 | 150 |
Reporting | 报告 | 150 | 250 |
· Test Report | · 测试报告 | 60 | 30 |
· Size Measurement | · 计算工作量 | 30 | 25 |
· Postmortem & Process Improvement Plan | · 事后总结, 并提出过程改进计划 | 30 | 10 |
合计 | 2180 | 2485 |