生成数独终局
函数
void Generate_Sudoku(int finals_num)
{
int sequence[9] = { 1,2,3,4,5,6,7,8,9 };//初始化排列数组
rest = finals_num;//剩余终局数
while (1) {
Secq2Final(sequence);//由排列数组生成数独终局,同时修改剩余终局数
//一次最多可以生成144个数独终局,终局数足够则不再生成
if (rest == 0)break;//如果数独终局数足够,则停止生成
next_permutation(sequence + 1, sequence + 8);//否则生成下一个排列数组继续生成数独终局
//是algorithm库中拥有的函数
}
Write2File();//把生成的数独终局写入文件当中,所有终局一次性输出到文件中
}
求解数独
函数
struct Puzzles //数独存储和管理结构
{
int sudoku[9][9];//数独谜题
int map[9][9];//每个格子有哪些数可以填写
int row[9];//每一行有哪些数可以填写
int col[9];//每一列有哪些数可以填写
int matrix[3][3];//每一个3*3方阵有哪些数可以填写
int empty;//还有几个未填写的格子
};
void Solve_Sudoku(char addr[])//解数独主体,在主函数中调用
{
do {
puz = ReadPuzzle(fr); //读入一个数独
Solve(puz); //求解数独,采用回溯法
} while ((ch = fgetc(fr)) != EOF);
Write2File1();//把解出的数独写入文件当中,所有终局一次性输出到文件中
}
void BackTrace(int t, Puzzles &puz) //回溯法求解数独
{
if (t > 80) { //找到一个解,将完成的数独赋值给result
result = puz;
return;
}
else {
int row = t / 9;
int col = t % 9;
if (puz.sudoku[row][col] != 0){ //如果当前方格有数,则跳至下一个方格
BackTrace(t + 1, puz);
return;
}
vector<int> able_set;//存储当前方格可能的数的集合
int matr_i = row / 3;
int matr_j = col / 3;
//通过与运算计算出当前方格可以填哪些数
int able = puz.row[row] & puz.col[col] & puz.matrix[matr_i][matr_j];
for (int i = 0; i < 9; i++)
{
if ((able % 2) == 1)
able_set.push_back(i + 1);
able /= 2;
}
//按顺序填写可能的数,并继续向下搜索
for (int i = 0; i < able_set.size(); i++)
{
Puzzles temp = puz;
//将temp数独的第row行col列填写able_set[i],并维护数独其他内容的正确性
Maintain(temp, row, col, able_set[i]);
if (CheckSudoku(temp) == TRUE)
BackTrace(t + 1, temp);
}
}
}
图是生成一百万个数独终局所需要的时间,在4s以内。
生成数独终局中,需要注意,C++中的文件流操作要比C语言中的文件输入函数要慢很多,且一次性输出到文件中所用的时间要远小于多次输入所用的时间。
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | ||
·Estimate | ·估计这个任务需要多少时间 | 30 | 60 |
Development | 开发 | ||
·Analysis | ·需求分析(包括学习新技术) | 100 | 180 |
·Design Spec | ·生成设计文档 | 90 | 60 |
·Design Review | ·设计复审(和同事审核设计文档) | 10 | 10 |
·Coding Standard | ·代码规范(为目前的开发制定合适的规范) | 30 | 40 |
·Design | ·具体设计 | 120 | 150 |
·Coding | ·具体编码 | 1500 | 1600 |
·Code Reivew | ·代码复审 | 120 | 120 |
·Test | ·测试(自我测试,修改代码,提交修改) | 150 | 120 |
Reporting | 报告 | 240 | 180 |
·Test Report | ·测试报告 | 150 | 120 |
·Size Measurement | ·计算工作量 | 30 | 60 |
·Postmortrm & Process Improvement Plan | ·事后总结,并提出过程改进计划 | 60 | 60 |
合计 | 2390 | 2580 |
总结
在解数独的过程中,如果是人来处理的话,肯定是先填写可填写的数字只有一个的或者可填写的数字较少的进行尝试,但是应用到计算机解决数独的时候,反而起到了反效果,也许是我的处理方式有问题吧。
由于不熟悉使用面向对象的思想,甚至对于一些概念至今依然不是十分明了,所以给代码的可读性以及安全性都带来了不同程度的影响。今后我也会加强使用面向对象的意识,以便尽快熟练掌握面向对象的思想。