数独的生成以及解答--回溯算法c++附详细代码
一,数独的规则
- 横向上9个数字满足1-9不重复;
- 竖向上9个数字满足1-9不重复;
- 将大网格拆分为9个3*3的小网格,每个小网格内同样满足1-9不重复
二,生成数独的思路
首先准备一个空的数独,从第一个格子开始,按照数独的规则,把1-9依次试探性的填入,如果合法,就填入.如果不合法就判断下一个数合不合法,这样,一直到把第81个格子填完,就生成了一个完整的数独,但是因为这样生成的数独是一个固定的,所以,现在我们要随机把它打乱,根据数独的特性,在同一个小九宫格中的行和行之间交换位置,列与列之间交换位置,数独依然成立,打个比方,第0行和第2行,交换位置,第0列和第2列交换位置,数独依然成立.
这样随机打乱位置后,再根据要求的难度,随机挖空其中的一些格子,这样就生成了我们需要的数独题目了!
bool isValid(int row, int col, int num, vector<vector<char>>&board){//检查行有没有重复的,如果有返回faulsefor (int i = 0; i < board.size(); i++){if (num == board[row][i]-'0'){return false;}}//检查列有没有重复的,如果有返回faulsefor (int i = 0; i < board.size(); i++){if (num == board[i][col]-'0')return false;}//检查数字所在的方块有没有重复的,如果有返回faulseint startrow = row / 3 * 3;int startcol = col / 3 * 3;int endrow = startrow + 3;int endcol = startcol + 3;for (int i = startrow; i < endrow; i++){for (int j = startcol; j < endcol; j++){if (num == board[i][j]-'0')return false;}}return true;}void swapCol(int m, int n, vector<vector<char>>& board){vector<char>temp(board.size(), ' ');for (int i = 0; i < board.size(); i++){temp[i] = board[i][m];board[i][m] = board[i][n];board[i][n] = temp[i];}}void selectBlank(int nums, vector<vector<char>>& board){srand(time(NULL));while (nums){int row = rand() % 9;int col = rand() % 9;if (board[row][col] != '.'){board[row][col] = '.';nums--;}}}void create(int blank, vector<vector<char>>& board){//小九宫格中的行和列交换,有以下9种交换方式int choice[9][2] = { {0,1},{0,2},{1,2},{3,4},{3,5},{4,5},{6,7},{6,8},{7,8} };srand(time(NULL));//设置动态种子for (int j = 0; j < 3; j++)//J代表交换次数,也可以不用这个循环,就交换一次{int i = rand() % 9;//取0-8之间的随机值board[choice[i][0]].swap(board[choice[i][1]]);//随机交换两行swapCol(choice[i][0], choice[i][1], board);//随机交换两列}selectBlank(blank, board);//根据难度可以选择不同数量的空格}
三,计算数独的思路
根据提供的数独,从第一个方格开始遍历,先判断是不是空,如果为空就把1-9依次试探性的填入,然后根据数独的规则,判断填入的数合不合法,如果合法就填入.然后递归遍历下一个方格,如果判断出下一个方格填入失败,说明现在填入的数是错的,需要回溯,然后把这个填入的数改为空,然后继续试探别的数字,如果所有数字试完都不行,那么就返回false,回溯到上一个数字.
这样直到把所有空格都遍历完成.
完整代码为:
// two.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//#include <iostream>
#include <vector>
#include <string>
#include <cstdlib>
#include <ctime>
#include<Windows.h>
using namespace std;class sudoku
{
public:bool active = false;sudoku(vector<vector<char>>&board){// printBoard(board);active = dfs(board, 0);}void printBoard(vector<vector<char>>&board){cout << " |---|---|---|---|---|---|---|---|---| " << endl;for (int i = 0; i < board.size(); i++){for (int j = 0; j < board.size(); j++){cout << " | " << board[i][j];}cout << endl;cout << " ---|---|---|---|---|---|---|---|---| " << endl;}}bool isValid(int row, int col, int num, vector<vector<char>>&board){//检查行有没有重复的,如果有返回faulsefor (int i = 0; i < board.size(); i++){if (num == board[row][i]-'0'){return false;}}//检查列有没有重复的,如果有返回faulsefor (int i = 0; i < board.size(); i++){if (num == board[i][col]-'0')return false;}//检查数字所在的方块有没有重复的,如果有返回faulseint startrow = row / 3 * 3;int startcol = col / 3 * 3;int endrow = startrow + 3;int endcol = startcol + 3;for (int i = startrow; i < endrow; i++){for (int j = startcol; j < endcol; j++){if (num == board[i][j]-'0')return false;}}return true;}void swapCol(int m, int n, vector<vector<char>>& board){vector<char>temp(board.size(), ' ');for (int i = 0; i < board.size(); i++){temp[i] = board[i][m];board[i][m] = board[i][n];board[i][n] = temp[i];}}void selectBlank(int nums, vector<vector<char>>& board){srand(time(NULL));while (nums){int row = rand() % 9;int col = rand() % 9;if (board[row][col] != '.'){board[row][col] = '.';nums--;}}}void create(int blank, vector<vector<char>>& board){//小九宫格中的行和列交换,有以下9种交换方式int choice[9][2] = { {0,1},{0,2},{1,2},{3,4},{3,5},{4,5},{6,7},{6,8},{7,8} };srand(time(NULL));//设置动态种子for (int j = 0; j < 3; j++)//J代表交换次数,也可以不用这个循环,就交换一次{int i = rand() % 9;//取0-8之间的随机值board[choice[i][0]].swap(board[choice[i][1]]);//随机交换两行swapCol(choice[i][0], choice[i][1], board);//随机交换两列}selectBlank(blank, board);//根据难度可以选择不同数量的空格}bool dfs(vector<vector<char>>&board, int start)//从0开始依次遍历81个格子,计算此数独{if (start == 81)//start=81,说明已经成功解出数独{return true;}else{bool ok = false;int row = start / 9;//根据此时方格的序号,计算出此方格的行和列int col = start % 9;if (board[row][col] == '.'){for (int i = 1; i <= 9; i++){if (isValid(row, col, i, board))//从1-9依次放入空格,并判断是否合法{board[row][col] = i + '0';//如果有数字合法,就写入该数字的字符ok = dfs(board, start + 1);//判断此方格的下一个方格是否成功写入if (!ok)//如果它的下一个方格是不合法的,说明它现在填入的数,不是正确的解,需回溯{board[row][col] = '.';//回溯}}}}else{ok = dfs(board, start + 1);}return ok;}}
};int main()
{/*vector<vector<char>>board = { vector<char>{'5','3','.','.','7','.','.','.','.'},vector<char>{'6','.','.','1','9','5','.','.','.'},vector<char>{'.','9','8','.','.','.','.','6','.'},vector<char>{'8','.','.','.','6','.','.','.','3'}, vector<char>{'4','.','.','8','.','3','.','.','1'}, vector<char>{'7','.','.','.','2','.','.','.','6'}, vector<char>{'.','6','.','.','.','.','2','8','.'}, vector<char>{'.','.','.','4','1','9','.','.','5'}, vector<char>{'.','.','.','.','8','.','.','7','9'}, };*/vector<vector<char>>blank(9, vector<char>(9,'.'));//创建一个9*9的空二维数组sudoku s(blank);s.create(50,blank);//创建50个空格的数独if (s.active){cout << "创建的数独为:" << endl;s.printBoard(blank);}elsecout << "数独表不合法,没有解!" << endl;s.dfs(blank, 0);//解数独函数if (s.active){cout << "此数独的解是:" << endl;s.printBoard(blank);}elsecout << "解题失败!" << endl;return 0;
}
数独的生成以及解答--回溯算法c++附详细代码相关推荐
- 用python求期望_Python——EM(期望极大算法)教学(附详细代码与注解)
今天,我们详细的讲一下EM算法. 前提准备 Jupyter notebook 或 Pycharm 火狐浏览器或谷歌浏览器 win7或win10电脑一台 网盘提取csv数据 需求分析 实现高斯混合模型的 ...
- Python——EM(期望极大算法)实战(附详细代码与注解)(二)
开始之前 各位朋友,大家好!针对上回讲的EM算法,有朋友反馈还是没弄清楚,今天,我再来详细的讲一下EM算法.请耐心食用本教程,滴滴滴~,上车! 前提准备 Jupyter notebook 或 Pych ...
- Python——EM(期望极大算法)实战(附详细代码与注解)(一)
开始之前 各位朋友大家好!今天我将带大家撸EM算法代码,在撸之前(呵呵,可别乱想≧◔◡◔≦),我们首先讲清楚什么是EM算法?为什么要用EM算法?.在这里我简要的介绍一下,大家都知道极大似然估计吧(至少 ...
- c语言二分法_14个经典C语言算法你就不看一眼?(附详细代码)
今天,给大家讲一讲,单片机常用的14个C语言算法(附详细代码)哟! 一.计数.求和.求阶乘等简单算法 此类问题都要使用循环,要注意根据问题确定循环变量的初值.终值或结束条件,更要注意用来表示计数.和. ...
- 基于MATLAB的三维数据插值拟合与三次样条拟合算法(附完整代码)
目录 一. 三维插值 例题1 二. 高维度插值拟合 格式一 格式二 格式三 格式四 格式五 例题2 三. 单变量三次样条插值 例题3 例题4 四. 多变量三次样条插值 例题6 一. 三维插值 首先三维 ...
- 实现最小生成树Kruskal算法(附完整代码)
实现最小生成树Kruskal算法(附完整代码) Kruskal算法是一种常见的计算最小生成树的算法.它的主要思想是将所有的边按照权值从小到大进行排序,并逐个加入到生成树中,如果加入后不会形成环,则保留 ...
- 【机器学习-分类】一句话+一张图说清楚朴素贝叶斯算法(附案例+代码)
说在前面 同一个算法本身存在各种不同的变体,即各种改进版本.一句话+一张图并不能涵盖所有情况,只是尽量用通俗的语言介绍其中经典的算法版本.希望对某算法本身不了解的人看完能迅速get到该算法在干什么:二 ...
- ECG:机器学习之预处理算法与R波定位算法(附部分代码)
ECG:机器学习之预处理算法与R波定位算法(附部分代码) 目前网上有关ECG信号处理的文章越来越多,说明这一块做的人也越来越多,但是网上的资源却很有限,而且很多资源都有一定的缺陷且不全.本文会对网上的 ...
- python重点知识归纳_一文了解机器学习知识点及其算法(附python代码)
一文了解机器学习知识点及其算法(附python代码) 来源:数据城堡 时间:2016-09-09 14:05:50 作者: 机器学习发展到现在,已经形成较为完善的知识体系,同时大量的数据科学家的研究成 ...
最新文章
- python txt文件读写(追加、覆盖)
- poj 3026 (最小生成树)
- Vue.js环境搭建
- 我们并没有觉得MapReduce速度慢,直到Spark出现
- 好看的粉色树洞表白墙网站源码
- Win10微软帐户切换不回Administrator本地帐户的解决方法【亲测】
- 函数式编程会取代GoF设计模式吗?
- 0基础学python要多久-27岁0基础自学Python,多久可以找到工作?
- MySQL优化详解(五)——MySQL分库分表
- DaVinci Resolve Studio 17.4.1 Mac(达芬奇调色软件)
- 美国专家声讨物联网安全 面对攻击如纸糊
- 137.只出现一次的数字II
- 乐吾乐 Topology 全新优化1.0已经内测啦
- linux用户是什么意思,Linux中的./是什么意思
- webview的白屏,和硬件加速
- 转移APK从手机到PC和PC到手机
- 安卓开发中的重力感应传感器
- docker安装包安装
- cs231n-LSTM_Captions
- python期货外盘不间断交易_外盘期货模拟交易【最新版】_数据API_数据应用_股票行情接口/API-云市场-阿里云...