数独生成
GitHub:sudoku
解题思路:
刚刚打开这次的作业的时候,我的第一想法是这道题的关键应该就是随机吧,于是第一时间我先拿去搜索了下c++中的随机函数。的确在[http://blog.csdn.net/weeendy/article/details/53195144]这个博文中找到了我想要的随机生成数的相关的函数代码。然后再开始思考该使用什么样的方法来实现。这时候,我也发现了这次的题目和之前做过的一道代码题八皇后问题有点类似。于是也就借鉴了之前自己的算法来进行尝试。
由于数独规则有三个:一是行不同,二是列不同,三是单元格不同。所以为了对填入的数字进行规则的检查,我选择使用三个9*9的数组,通过不同的放置规则来达到更快检查的目的。
设计实现:
首先,由于肯定会多次进行检查是否合格,所以检测数字是否能正确放入棋盘中的函数肯定是要有的。其次,用于实现算法的,还有一个实现回溯的函数。还有一个进行初始化各个棋盘的函数。
代码说明:
以下此函数,是用来检测数字是否能正确放入棋盘中的。其中b是用于判断在列中是否已经存在该数字,c是判断是否在3*3的格子里存在该数字,而d是判断在行中是否存在该数字。
int judge(int x,int y,int count) {
int z;
if (a[x][y])//判断该位置是否已有数字
return 0;
else if (b[y][count - 1] == 1)//判断在第y列中是否已经存在该数字
return 0;
else if (d[x][count - 1] == 1)
return 0;
z = (x - (x % 3)) + ((y - (y % 3))/3);
if (c[z][count - 1] == 1)
return 0;
a[x][y] = count;
b[y][count - 1] = 1;
c[z][count - 1] = 1;
d[x][count - 1] = 1;
return 1;
}
以下这个函数,是用来实现回溯算法的核心代码。它尝试分步的去测试每一个数字,并且我是在数字随机的情况下,以行为标准,一行一行的放入数字。如果1到9都不合格则进行回溯。(ps:这里的代码思想也是参考了一些百度上面的方法。分别是遍历数组的同时,将当前元素与数组中随机位置的元素交换,实现将数组随机排序。还有测试数独规则的时候,第三个规则,九宫格的时候参考了[http://blog.csdn.net/jiejinquanil/article/details/53463298] 这位前辈的方法。
bool recursion(int x,int y) {
int ran_num, num[9];
for (int i = 0; i < 9; i++) {
num[i] = i+1;
}
srand((unsigned)time(0));//从网上学到的根据系统时间来生成的随机数的方法
for (int i = 0; i < 9; i++) {
ran_num = rand() % 9;
swap(num[i], num[ran_num]);//使用随机函数来产生1到9的随机数
}
for (int i = 0; i < 9; i++) {
int count = num[i];
if (count == 9 && (x == 0 || y == 0)) {
if (x == 0 && y == 0) {
recursion(x, y + 1);
return true;
}
}
if (judge(x, y, count) == 1) {
if (y == 8) {
if (x == 8)//第一种情况:数独已经形成
return true;
else if (recursion(x + 1, 0))//第二种情况:这一行已经遍历完了
return true;
}
else {
if (recursion(x, y + 1))
return true;
}
a[x][y] = 0;
b[y][count - 1] = 0;
c[(x - (x % 3)) + ((y - (y % 3))/3)][count - 1] = 0;
d[x][count - 1] = 0;
}
}
return false;
}
测试运行:
效能分析与改进:
分析时生成的数独个数设为50000个
发现了一个问题,善用百度真的可以解决很多问题
PSP 2.1表格:
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 712 | 1245 |
· Estimate | · 估计这个任务需要多少时间 | 712 | 1245 |
Development | 开发 | 652 | 1155 |
· Analysis | · 需求分析 (包括学习新技术) | 120 | 150 |
· Design Spec | · 生成设计文档 | 2 | 5 |
· Design Review | · 设计复审 (和同事审核设计文档) | 10 | 30 |
· Coding Standard | · 代码规范 (为目前的开发制定合适的规范) | 10 | 30 |
· Design | · 具体设计 | 100 | 150 |
· Coding | · 具体编码 | 240 | 360 |
· Code Review | · 代码复审 | 50 | 70 |
· Test | · 测试(自我测试,修改代码,提交修改) | 120 | 360 |
Reporting | 报告 | 60 | 90 |
· Test Report | · 测试报告 | 30 | 30 |
· Size Measurement | · 计算工作量 | 30. | 60 |
· Postmortem & Process Improvement Plan | · 事后总结, 并提出过程改进计划 | 20 | 30 |
合计 | 712 | 1245 |
个人总结:
这次的代码题给我的冲击力还是很大的,因为首先是久不敲代码所带来的生疏感,二是算法上的匮乏。居然还是只能吃老本,这种情况真的是很让人难受。也让我下定决心,好好研究下算法上的知识,真的是很有必要。