看到CSDN上有位大神用C#写了一个破解数独的程序(点击打开链接),不过我对C#也不懂,比较喜欢C++,就用标准C++也写了一个,希望各位喜欢。三纯程序,纯控制台程序,纯各人爱好,纯算法程序,无win API。基本思路与之前那个类似,采用brute force加剪枝,找到第一个符合条件的情况就立即退出不再查找。一般一个合格的数独只有唯一解,如果你的数独多解的话,那也就不叫数独了。

代码如下:

#include <iostream>
#include <deque> using namespace std; const int MAX_SIZE = 9; // 九宫格 struct Pos {
Pos(int x, int y) : row(x), col(y) {};
int row;
int col;
}; typedef deque <Pos> qpos;
qpos Q; // 记录要放置数字的位置 // 九宫格数组,0表示玩家要放置数字的位置
int sudoku[MAX_SIZE][MAX_SIZE] = {
{0, 0, 3, 0, 5, 0, 0, 0, 9},
{0, 0, 0, 1, 0, 0, 0, 2, 5},
{0, 8, 0, 0, 3, 7, 0, 0, 0},
{0, 0, 0, 0, 0, 8, 0, 9, 7},
{2, 0, 0, 0, 6, 0, 0, 0, 4},
{9, 4, 0, 0, 0, 0, 8, 0, 1},
{0, 0, 0, 6, 9, 0, 4, 0, 0},
{8, 0, 0, 0, 0, 5, 0, 0, 0},
{6, 0, 0, 0, 1, 0, 9, 0, 0},
}; void printSudoku()
{
cout << "-------------------------" << endl;
for (int i = 0; i < MAX_SIZE; i++) {
for (int j = 0; j <MAX_SIZE; j++) {
if (j % 3 == 0) {
cout << "| ";
}
cout << sudoku[i][j] << " ";
}
cout << "| "; cout << endl;
if ( (i+1) % 3 == 0 ) {
cout << "-------------------------" << endl;
}
}
} bool check(Pos p, int n)
{
int cur_row = p.row;
int cur_col = p.col;
// 验证行列是否合格
for (int i = 0; i < MAX_SIZE; i++) {
if (n == sudoku[i][cur_col] || n == sudoku[cur_row][i]) {
return false;
}
} // 验证九宫格内是无复生数字
int grid_row = ( cur_row / 3 ) * 3;
int grid_col = ( cur_col / 3 ) * 3;
for (int i = 0; i < 3; i++) {
if (n == sudoku[grid_row][i + grid_col] ||
n == sudoku[grid_row + i][grid_col]) {
return false;
}
} return true;
} bool place(qpos & Q)
{
// 递归结束条件为没有要断续放置数字的位置
if (Q.empty()) {
printSudoku();
return true;
}
Pos cur(Q.front().row, Q.front().col); // 当前需要放置的位置信息
Q.pop_front();
for (int i = 1; i <= 9; i++) { // 从1到9轮流尝试
if ( check(cur, i) ) {
sudoku[cur.row][cur.col] = i; // 放置数字i到当前位置
if ( !place(Q) ) { // 放置下一位置
// 下一位置放置失败,则在当前位置尝试放置下一个i
sudoku[cur.row][cur.col] = 0; // 将当前位置值重置
} else { // 下一位置放置成功
return true;
}
}
}
Q.push_front(cur); //当前位置不论怎么放置数字,下一位置都无法放置成功,
// 重新插入该位置信息,返回上一级放置位置
return false;
} int main()
{
// Q中保存需要放置数字的位置
for (int i = 0; i < MAX_SIZE; i++) {
for (int j = 0; j < MAX_SIZE; j++) {
if (0 == sudoku[i][j]) {
Q.push_back(Pos(i, j));
}
}
} place(Q); return 0;
}

我也来个运行截图:

上面的程序只会打印出一种符合的数独,如果你想将所以可能的情况都打印出来怎么办,一般情况下,合格的数独都只有一种解,那万一有一个不合格的数独,你又想知道它的全部解,那么,你可以用下面的方法:

/**
* 打印所有符合条件的情况
*/
void place2(qpos & Q)
{
// 递归结束条件为没有要断续放置数字的位置
if (Q.empty()) {
printSudoku();
return;
}
Pos cur(Q.front().row, Q.front().col); // 当前需要放置的位置信息
Q.pop_front();
for (int i = 1; i <= 9; i++) { // 从1到9轮流尝试
if ( check(cur, i) ) {
sudoku[cur.row][cur.col] = i; // 放置数字i到当前位置
place2(Q);
sudoku[cur.row][cur.col] = 0; // 将当前位置值重置
}
}
Q.push_front(cur); // 重新插入该位置信息,返回上一级放置位置
}

C++ 完美破解九宫格(数独)游戏的更多相关文章

  1. android开发——数独游戏

    最近研究了一下android,写了一个数独游戏,具体如下: 游戏界面需要重写一个ShuduView继承View, 然后自定义一个Dialog: 1.需要继承 Dialog 类, 2.并要定义一个有参构 ...

  2. C语言学习 数独游戏

    摘要:花了1周多时间学习了C语言,开始练手写解数独游戏的程序. C语言学习 数独游戏 作者:乌龙哈里 时间:2015-11-22 平台:Window7 64bit,TCC 0.9.26(x86-64 ...

  3. OpenCV 玩九宫格数独(二):knn 数字识别

    欢迎大家关注腾讯云技术社区-博客园官方主页,我们将持续在博客园为大家推荐技术精品文章哦~ 作者:刘潇龙 前言 首先需要说明,这里所说的数字识别不是手写数字识别! 但凡对机器学习有所了解的人,相信看到数 ...

  4. 【DFS】数独游戏

    DFS(深度优先搜索): 深度优先搜索算法(英语:Depth-First-Search,简称DFS)是一种用于遍历或搜索树或图的算法. 沿着树的深度遍历树的节点,尽可能深的搜索树的分支.当节点v的所在 ...

  5. 创建随机的9x9数独游戏终盘并打印

    创建随机的9x9数独游戏终盘并打印 项目github地址 1. 项目相关要求 1.1 要求 利用程序随机构造出N个已解答的9x9数独棋盘 . 输入 数独棋盘题目个数N(0<N<=10000 ...

  6. iOS开发 Swift开发数独游戏(四) 游戏界面的界面与逻辑

    一.游戏界面涉及到的功能点 1)数独格子的建模 (1)绘制数独格子要考虑到标记功能 所以要在每个格子内预先塞入9个标记数字,仅数独格子算下来就有9*9*9=729个格子且存在大量嵌套(这导致我在操作S ...

  7. Leetcode0037--Sudoku Solver 数独游戏

    [转载请注明]http://www.cnblogs.com/igoslly/p/8719622.html 来看一下题目: Write a program to solve a Sudoku puzzl ...

  8. 对回溯算法的理解(以数独游戏为例,使用c++实现)

    算法思想: 数独游戏的规则: 每一行都用到1.2.3.4.5.6.7.8.9位置不限: 每一列都用到1.2.3.4.5.6.7.8.9位置不限: 每3×3的格子(共九个这样的格子)都用到1.2.3.4 ...

  9. 基于第二次数独游戏,添加GUI界面

    高级软件工程第三次作业:基于第二次数独游戏,添加GUI界面.GUI界面代码如下: package firstGui; import java.awt.*; import java.awt.event. ...

随机推荐

  1. C#中的委托和事件2-2(转)

    引言 如果你看过了 C#中的委托和事件2-1 一文,我想你对委托和事件已经有了一个基本的认识.但那些远不是委托和事件的全部内容,还有很多的地方没有涉及.本文将讨论委托和事件一些更为细节的问题,包括一些 ...

  2. LRU缓存算法 - C++版

    LRU是Least Recently Used的缩写,意思是最近最少使用,它是一种Cache替换算法. 实现思路: hashtable + 双向链表 时间复杂度: 插入,查找,删除:O(1) 空间使用 ...

  3. SCM管理器

    OpenSCManager 打开SCM管理器 CloseServiceHandle 关闭句柄 CreateService 创建服务 OpenService 打开服务 ControlService 控制 ...

  4. 02 - 替换SetInput方法 VTK 6.0 迁移 (2013-06-30 16:22)

    VTK6 引入了许多不兼容的变化,这其中就包括用SetInputData()和SetInputConnection()替换SetInput()方法.在先前的版本中,VTK4 引入了SetInput() ...

  5. Largest product in a grid

    这个比前面的要复杂点,但找对了规律,还是可以的. 我逻辑思维不强,只好画图来数数列的下标了. 分四次计算,存入最大值. 左右一次,上下一次,左斜一次,右斜一次. In the 2020 grid be ...

  6. 51单片机C语言学习笔记4:keil C51绝对地址访问

    在利用keil进行8051单片机编程的时,常常需要进行绝对地址进行访问.特别是对硬件操作,如DA AD 采样 ,LCD 液晶操作,打印操作.等等.C51提供了三种访问绝对地址的方法: 1. 绝对宏:  ...

  7. web前端框架选型

    1.1.界面使用脚本语言有html5,php5,css3,js动态库jquery等 1.2.html采用技术为最新html5技术,html5生成的页面在phone.pad.Phablets.pc也可方 ...

  8. 嵌入式linux内核制作

    今天来总结一下mini2440的内核制作过程. 一. 将内核文件拷贝至目标目录,解压. 二.清除中间文件 命令:make distclean 三.配置内核文件 将开发板厂商制作好的内核文件拷贝至内核文 ...

  9. 【转】BT5无法找到软件安装包(提供可用的BT更新源)

    像我这种一般想起才玩玩BT5的人,跟不上讯息的变化. 偶尔想尝试某个实验,然后去安装,发现提示无法找到软件安装包. 这个时候,应该注意到,现在已经从BT5到kali了,假如想我这种人,肯定比较少留意软 ...

  10. HDU5107---K-short Problem (线段树区间 合并、第k大)

    题意:二维平面上 N 个高度为 Hi 建筑物,M次询问,每次询问输出 位于坐标(x ,y)左下角(也就是xi <= x && yi <= y)的建筑物中的第k高的建筑物的高 ...