1) GitHub地址
https://github.com/ChengHaoShi/Project
2) PSP表格
PSP2.1 |
Personal Software Process Stages |
预估耗时(小时) |
实际耗时(小时) |
Planning |
计划 |
1.5 |
1 |
·Estimate |
|
1.5 |
1 |
|
·开发 |
44.5 |
41.5 |
|
12 |
16 |
|
·Design Spec |
|
8 |
5 |
|
3 |
4 |
|
|
1 |
2 |
|
|
5 |
4 |
|
|
5.5 |
4 |
|
|
3.5 |
4 |
|
|
4.5 |
2.5 |
|
Reporting |
报告 |
5 |
6 |
|
1.5 |
1 |
|
|
1 |
2.5 |
|
|
2.5 |
2.5 |
|
合计 |
51 |
48.5 |
3) 解题思路
- ·数独游戏规则:
数独是源自18世纪瑞士的一种数学游戏。是一种运用纸、笔进行演算的逻辑游戏。玩家需要根据9×9盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行、每一列、每一个粗线宫(3*3)内的数字均含1-9,不重复。数独盘面是个九宫,每一宫又分为九个小格。在这八十一格中给出一定的已知数字和解题条件,利用逻辑和推理,在其他的空格上填入1-9的数字。使1-9每个数字在每一行、每一列和每一宫中都只出现一次,所以又称“九宫格”。 ———引用自《数独_百度百科》
·题目要求:
1.程序能生成不重复的数独终局至文件;
2.程序能读取文件内的数独问题,求一个可行解并将结果输出到文件;
·采用算法:
回溯法生成数独终局,并检验是否符合数独可行解。
4) 设计实现过程
将部分函数和变量封装成Sudoku类。6个Sudoku类函数:
构造函数void Sudoku(int n)
公有函数int SudokuGenerate(int pos, long& count), void SudokuSolve(char* path)
私有函数bool IsVaild(int pot)、void PrintSudoku()
控制台输出函数void PrintUsage()
单元测试设计:
对IsValid() 函数进行测试;
对命令行进行测试,检测异常输入并提供解决办法;
对队中生成数独的个数进行测试;
5) 程序使用方法
1.序每次向sudoku.txt文件中输入一个数独终局。
2.使用release进行程序生成。
性能分析图
int SudokuGenerate(int pos, long& count, bool solve);//程序中消耗最大的函数
6) 核心代码
#include "sudoku.h" #include "stdafx.h" using namespace std; string const NOSUCHFILE = "No such file: "; string const OUTFILE = "sudoku.txt"; int const SQRTSIZE = int(sqrt(GRIDSIZE)); Sudoku::Sudoku(int n) { for (int i = 0; i < GRIDSIZE; i++) { for (int j = 0; j < GRIDSIZE; j++) { grid[i][j] = UNKNOWN; } } grid[0][0] = FLAGNUM; this->n = n; output.open(OUTFILE); for (int i = 0; i < GRIDSIZE * GRIDSIZE; i++) { if ((i + 1) % 9 == 0) { buff[2 * i + 1] = ‘\n‘; continue; } buff[2 * i + 1] = ‘ ‘; } buff[162] = ‘\n‘; } int Sudoku::SudokuGenerate(int pos, long& count, bool solve) { if (pos == GRIDSIZE * GRIDSIZE) { PrintSudoku(); count++; if (count == n) { return 1; } } else { int x = pos / GRIDSIZE; int y = pos % GRIDSIZE; if (grid[x][y] == UNKNOWN) { int base = x / 3 * 3; for (int i = 0; i < GRIDSIZE; i++) // try to fill the pos from 1-9 { grid[x][y] = (i + base) % GRIDSIZE + 1 + ‘0‘; if (IsValid(pos, solve)) // if the number is valid { if (SudokuGenerate(pos + 1, count, solve) == 1) // try to fill next pos { return 1; } } grid[x][y] = UNKNOWN; } } else { if (SudokuGenerate(pos + 1, count, solve) == 1) { return 1; } } } return 0; } int Sudoku::SudokuSolve(char* path) { ifstream input; input.open(path); if (input) { int total = 0; string temp[GRIDSIZE]; string str; int line = 0; bool exc = false; // wrong input such as ‘a‘,‘.‘,etc. in the input file while (total < 1000000 && getline(input, str)) { temp[line] = str; line++; if (line == GRIDSIZE) { for (int i = 0; i < GRIDSIZE; i++) { for (int j = 0; j < GRIDSIZE; j++) { grid[i][j] = temp[i][2 * j]; if(grid[i][j] < ‘0‘ || grid[i][j] > ‘9‘) { exc = true; break; } } } getline(input, str); line = 0; if (exc) { exc = false; continue; } total++; // solve sudoku long count = 0; SudokuGenerate(0, count, true); } } //cout << total << endl; } else { cout << NOSUCHFILE << string(path) << endl; return 0; } return 1; } bool Sudoku::IsValid(int pos, bool solve) { int x = pos / GRIDSIZE; int y = pos % GRIDSIZE; int z = x / SQRTSIZE * SQRTSIZE + y / SQRTSIZE; int leftTop = z / SQRTSIZE * GRIDSIZE * SQRTSIZE + (z % SQRTSIZE) * SQRTSIZE; int rightDown = leftTop + (2 * GRIDSIZE + SQRTSIZE - 1); int bound = solve ? GRIDSIZE : y; // check row for (int i = 0; i < bound; i++) { if (i == y) { continue; } if (grid[x][i] == grid[x][y]) { return false; } } // check column bound = solve ? GRIDSIZE : x; for (int i = 0; i < bound; i++) { if (i == x) { continue; } if (grid[i][y] == grid[x][y]) { return false; } } // check box int bound_x = leftTop / GRIDSIZE; int bound_y = leftTop % GRIDSIZE; if (bound_x % 3 != 0 || bound_y % 3 != 0 || bound_x > GRIDSIZE -3 || bound_y > GRIDSIZE - 3) { cout << "error" << endl; exit(0); } for (int i = bound_x; i < (bound_x + 3); i++) { for (int j = bound_y; j < (bound_y + 3); j++) { if (i == x && j == y) { if (solve) { continue; } else { return true; } } if (grid[i][j] == grid[x][y]) { return false; } } } return true; } void Sudoku::PrintSudoku() { for (int i = 0; i < GRIDSIZE; i++) { for (int j = 0; j < GRIDSIZE; j++) { buff[18 * i + 2 * j] = grid[i][j]; } } output << buff; }
原文地址:https://www.cnblogs.com/AmandaYoung/p/8726878.html