看到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. Oracle database启动过程分析

    实例跟数据库的区别 实例(instance)是内存中的一块区域和一组后台进程的集合.它的作用是维护数据库文件的.而数据库(database)则是指存放数据的数据库文件.它是一系列格式化的数据的集合.它 ...

  2. C语言刷新缓冲区(转载)

    C语言中有几个基本输入函数: //获取字符系列 int fgetc(FILE *stream); int getc(FILE *stream); int getchar(void); //获取行系列 ...

  3. Visual Studio调试之断点进阶篇

    Visual Studio调试之断点进阶篇 在上一篇文章Visual Studio调试之断点基础篇里面介绍了什么是断点,INT 是Intel系列CPU的一个指令,可以让程序产生一个中断或者异常.程序中 ...

  4. Facebook 正式开源其大数据查询引擎 Presto

    Facebook 正式宣布开源 Presto —— 数据查询引擎,可对250PB以上的数据进行快速地交互式分析.该项目始于 2012 年秋季开始开发,目前该项目已经在超过 1000 名 Faceboo ...

  5. cf D. Broken Monitor

    http://codeforces.com/contest/370/problem/D 题意:输入一张图,上面只有两个字符'w'和‘.’ ,如果可以用一个正方形把所有的‘w’围起来,所有的‘w’都在正 ...

  6. java各种排序实现

    排序是程序开发中一种非常常见的操作,对一组任意的数据元素(或记录)经过排序操作后,就可以把他们变成一组按关键字排序的有序队列. 对一个排序算法来说,一般从下面3个方面来衡量算法的优劣: 时间复杂度:它 ...

  7. (转)linux中常用的头文件

    头文件主目录include 头文件目录中总共有32个.h头文件.其中主目录下有13个,asm子目录中有4个,linux子目录中有10个,sys子目录中有5个.这些头文件各自的功能如下,具体的作用和所包 ...

  8. 【转】如何在 Android 程序中禁止屏幕旋转和重启Activity

    原文网址:http://www.cnblogs.com/bluestorm/p/3665890.html 禁止屏幕随手机旋转变化 有时候我们希望让一个程序的界面始终保持在一个方向,不随手机方向旋转而变 ...

  9. cxgrid按条件计算合计值 TcxTreeList计算合计值

    在Footer的第一列显示[合计:] 加一个Summary项,Column设为Grid的第一列,Kind设为skNone 在该Summary项的OnGetText事件中,输入: procedure T ...

  10. Delphi EurekaLog 调试内存泄露方法

    要使用EurekaLog进行内存泄露检测,需要手动开启"EurekaLog Options..."下的"Advanced Options"旁的"Mem ...