9x9的正方形方格可以分成9个3×3的九宫格。
数独游戏是在这样的正方形中,首先事先给某些方格填入1-9的数字,然后要求在余下的方格中也填入1-9的数字,要求每一行,每一列,以及每个九宫格中,都正好包含1-9这九个数字。

解算 sudoku 的方法很多,前段时间闲的无聊我也写了一个。算法很简单,就是试填+递归穷举。方法有些暴力,不过很有效,程序也非常的简洁。

实际上,写完程序后我才发现,sudoku 的难点其实不在解算,而是如何生成数独题目,并且保证生成的题目解是唯一的。这个问题还要再思考思考,现在还没有什么思路。

下面是源程序,C语言写的,尽可能的使其保持 KISS (keep it simple and stupid)

sudoku 函数求出一个解。

sudoku_all 函数则试图穷举所有可行解。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 9
void display(char mat[SIZE][SIZE], char mes[]);
void copy(char src[SIZE][SIZE], char des[SIZE][SIZE]);
bool containInRow(char mat[SIZE][SIZE], int element, int row);
bool containInCol(char mat[SIZE][SIZE], int element, int col);
bool containInBlock(char mat[SIZE][SIZE], int element, int row, int col);
bool findFirstEmptyPos(char mat[SIZE][SIZE], int pos[2]);
void load(char mat[SIZE][SIZE]);
bool sudoku(char mat[SIZE][SIZE]);
bool sudoku_all(char mat[SIZE][SIZE]);
static int solution_count = 0;
static char message[] = "the number of possible solution is 9999999:";
int main(void)
{
int i, j, t, ret;
bool isOk;
char mat[SIZE][SIZE];
solution_count = 0;
load(mat);
display(mat, "origin matrix is ");
isOk = sudoku_all(mat);
if( isOk )
display(mat, "solved matrix is ");
// else
//  puts("No valid solution");
printf("the number of possible solution is %d:", solution_count);
// puts(message);
return 0;
}
bool sudoku(char mat[SIZE][SIZE])
{
char b[SIZE][SIZE];
bool isOk;
int pos[2], j;
copy(mat, b);
isOk = findFirstEmptyPos(b, pos); // 找到第一个需要填的位置
if(isOk == false) return true; // 如果都填满了,返回 true. 表示成功的找到解了
for(j = 1; j <= SIZE; j ++)
{
if( containInRow(b, j, pos[0]) ) continue;
if( containInCol(b, j, pos[1]) ) continue;
if( containInBlock(b, j, pos[0], pos[1]) ) continue;
b[ pos[0] ][ pos[1] ] = j; // j 是一个可以填的值,试填之
isOk = sudoku( b );
if(isOk == true)
{
copy(b, mat); // 到这里了说明 j 填对了,并且后面的数也都填好了
return true;  // 因此将结果拷贝到 mat 中。
}
copy(mat, b); // 到这里说明 j 填的不对,恢复 b ,重新填
}
return false; // 到这里了说明 1-9都试了全都不对,表明当前状态无解
}
bool sudoku_all(char mat[SIZE][SIZE]) //解出所有的可行解
{
char b[SIZE][SIZE];
bool isOk = false;
int pos[2];
copy(mat, b);
// display(mat, "inter");
isOk = findFirstEmptyPos(b, pos); // 找到第一个需要填的位置
if(isOk == false)
{
solution_count ++;
sprintf(message, "A possible solution (%d):", solution_count);
//  puts(message);
display(mat, message);
return false; //找到一组解后,仍然返回 false, 让程序继续找下一组解
}
for(int j = 1; j <= SIZE; j ++)
{
if( containInRow(b, j, pos[0]) ) continue;
if( containInCol(b, j, pos[1]) ) continue;
if( containInBlock(b, j, pos[0], pos[1]) )continue;
b[ pos[0] ][ pos[1] ] = j; // j 是一个可以填的值,试填之
isOk = sudoku_all( b ); // 无论找到解没有,都还原成原始状态,接着找下一组解
copy(mat, b);  // 因为如果找到解了,解就已经用 display 函数输出了,接着找下一组解就可以了。
}                  // 如果没找到解,同样也要恢复原始状态,试下一个可能的数
return false; // 到这里了说明 1-9都试了全都不对,表明当前状态无解,返回到上一步,试下一个可能的数
}
void load(char mat[SIZE][SIZE])
{
int i, j, t;
for ( i = 0; i < SIZE; i++)
{
for (j = 0; j < SIZE ; j++)
{
scanf("%d", &t);
mat[i][j] = t;
}
}
}
void display(char mat[SIZE][SIZE], char mes[])
{
int i, j, t;
puts(mes);
for ( i = 0; i < SIZE; i++)
{
for (j = 0; j < SIZE ; j++)
{
t = mat[i][j];
printf("%2d ", t);
}
puts("");
}
}
/**
* @brief 判断一个数是否已经在这一行出现过了
*/
bool containInRow(char mat[SIZE][SIZE], int element, int row)
{
int i;
for (i = 0; i < SIZE; i++)
{
if (mat[row][i] == element) return true;
}
return false;
}
/**
* @brief 判断一个数是否已经在这一列出现过了
*/
bool containInCol(char mat[SIZE][SIZE], int element, int col)
{
int i;
for (i = 0; i < SIZE; i++)
{
if (mat[i][col] == element) return true;
}
return false;
}
/**
* @brief 判断一个数是否已经在这一3*3的小方块中出现过了
*/
bool containInBlock(char mat[SIZE][SIZE], int element, int row, int col)
{
int i = row / 3;
int j = col / 3;
for (int ii = 0; ii < SIZE / 3; ii++)
{
for(int jj = 0; jj < SIZE / 3; jj++)
{
if (mat[i * 3 + ii][j * 3 + jj] == element) return true;
}
}
return false;
}
void copy(char src[SIZE][SIZE], char des[SIZE][SIZE])
{
int i, j;
for (i = 0; i < SIZE; i++)
{
for (j = 0; j < SIZE; j++)
{
des[i][j] = src[i][j];
}
}
}
/**
* @brief 找到第一个需要填数字的位置
* @para pos 通过 pos 返回位置坐标, pos[0] 为行号, pos[1] 为列号
*/
bool findFirstEmptyPos(char mat[SIZE][SIZE], int pos[2])
{
int i, j;
for (i = 0; i < SIZE; i++)
{
for (j = 0; j < SIZE; j++)
{
if (mat[i][j]  == 0)
{
pos[0] = i;
pos[1] = j;
return true;
};
}
}
return false;
}

数独(sudoku)游戏的程序求解相关推荐

  1. java数独游戏_java 数独sudoku游戏

    有大佬帮帮看下这个数独游戏程序么,检测为空.有效都成功了,就是不能把赋值更新到数组里面,一直重复打印原数组 package pro1; import java.util.Scanner; public ...

  2. 【2019.09.19】数独(Sudoku)游戏之我见(软工实践第三次作业)

    Github项目地址:https://github.com/MokouTyan/suduku_131700101 [2019.09.20]更新:代码经过Code Quality Analysis工具的 ...

  3. 一段代码,求解数独(九宫格)游戏

    数独(Sudoku)游戏是从1-9共9个数字中,装在3x3x3x3的单元格内 每个小的3x3内的数值只能重复一遍,同时每行及每列的数值也只能重复一遍 每个单元格都必须有数值,不能留空 解法简介: 创建 ...

  4. 独数游戏android程序,Android 数独小游戏

    先看看效果图 sudoku-o3.gif 数独设计思路 先看布局,我们可以看到数独由9x9的格子组成,每个格子中间有一个数字. Cell (单个格子.android 中我们可以先用TextView代替 ...

  5. 谈谈数独(Sudoku)

    谈谈 Sudoku (数独) 除特别说明外,本文提到的Sudoku是指9x9的经典Sudoku.本文大量参考了维基百科的相关条目. Sudoku 介绍 Sudoku 是一种数学游戏,把一个9行9列的棋 ...

  6. 数独终局生成及残局求解

    文章目录 一.项目地址 二.各模块开发时间预估 三.学习过程.解题思路 3.1 开发语言及运行环境 3.2 项目要求分析 3.2.1 需求建模 3.2.2 数据流设计方法 3.3 解题思路 3.3.1 ...

  7. BIT软件工程个人项目——数独sudoku

    BIT软件工程个人项目--数独sudoku 目录: (点击可页内跳转) 1. 项目地址 2. PSP表格 3. 解题思路描述 --3.1初期思考 --3.2数独终局生成 --3.3求解数独 4. 设计 ...

  8. Java黑皮书课后题第8章:*8.24(检验数独的解决方案)程序清单8-4通过检测棋盘上的每个数字是否是有效的,从而检验一个解决方案是否是有效的。重写该程序,通过检验是否每行、每列、每个小方盒中具有

    *8.24(检验数独的解决方案)程序清单8-4通过检测棋盘上的每个数字是否是有效的,从而检验一个解决方案是否是有效的.重写该程序 题目 题目描述 程序清单8-4 破题 代码 题目 题目描述 *8.24 ...

  9. Android Studio实现数独小游戏,休闲益智

    文章目录 一.项目概述 二.开发环境 三.详细设计 3.1 界面设计 3.2 逻辑设计 四.运行演示 五.源码获取 一.项目概述 数独是一种逻辑解谜游戏,它规则稍复杂,解题过程富有挑战性.本次安卓数独 ...

最新文章

  1. 22.调用delay()方法延时执行动画效果
  2. 443 ERROR [main] client.ConnectionManager$HConnectionImplementation: Can‘t get connection to ZooKeep
  3. VTK:Picking之HighlightSelectedPoints
  4. MS CRM 2011 汇总更新4已经发布
  5. VisualSVN Server 和 SVN 服务器架设
  6. cartographer编译过程遇到未定义的dlclose@@GLIBC_2.2.5
  7. Kaldi AMI数据集脚本学习7---train_deltas.sh
  8. pythonmysql包_[Python] MySQLdb(即 MySQL-python 包)在 OS X 中安装指南
  9. Mac便笺基本操作|便笺使用太鸡肋?那是你不知道这几个快捷键!
  10. mybatis自动生成代码
  11. ios vue 添加本地音乐_vue怎么添加自己的音乐
  12. WAP1.x协议栈浅析
  13. Geek(一个好用的强力卸载软件工具,包括注册表所有依赖项全部清理掉)
  14. mindoc mysql_MinDoc 配置文件详解
  15. zabbix配置方糖微信推送报警
  16. python中np是什么意思_了解python中np是做什么的
  17. VS2022无法启动程序,系统找不到指定文件
  18. the sip module implements API v12.0 to v12.8 but the PyQt5.QtGui module requires API v12.9
  19. android+获取电池信息,Delphi XE5 Android应用程序获取电池信息
  20. Git 之三 常用命令:仓库创建、提交、分支等

热门文章

  1. Windows平台的x64dbg插件合集
  2. 【微生物研究】微生物交互关系研究论文摘要集锦
  3. 诗经2 国风-周南-葛覃
  4. 鸿蒙系统北斗导航系统,这个“北斗导航” App,竟欺骗了几百万人!
  5. 经常忘记的--jsp被转成servlet放在哪个目录下呢 2、日志路径3、AdminServer.lok
  6. 音乐雷达 shazam算法_Shazam之类的音乐识别应用程序如何工作?
  7. 一个流氓软件会有哪些典型特征?
  8. echarts自定义legend样式
  9. python 的csr_python稀疏矩阵(CSR型)操作
  10. recat 基本学习