数独
文章目录
前言
数独
每个谜题都由一个在不同位置给与提示数字的9x9网格组成。游戏的目的是将空方格填上数字,使得每一行,每一列以及每一个3x3宫都没有重复的数字出现。
深搜解法(Java)
练习dfs的基础题目(如有错误欢迎评论指正谢谢)
每行都有注释嗷~
代码如下(示例):
import java.util.Arrays;
import java.util.Scanner;
public class 数独游戏 {
public static void main(String[] args) {
// dfs()
Scanner sc = new Scanner(System.in);
// sc.nextLine();
// 生成二维数组用于存储输入的数据
char[][] chars = new char[9][];
// 循环读入数据
for (int i = 0; i < 9; i++) {
chars[i]=sc.nextLine().toCharArray();
}
// 数据读入完成 开始dfs
dfs(chars,0,0);
}
private static void dfs(char[][] chars, int x, int y) {
// 定义出口
// 当我的列已经达到9 说明已经dfs完成 将即得的结果进行打印输出
if(x==9){
print(chars);
// 程序递归了很多层 这里直接退出程序
System.exit(0);
}
// 找到了一个需要进行填数的位置
if(chars[x][y]=='0'){
// 我们从1~9选一个进行填入
for (int i = 1; i <=9; i++) {
// 对如填入的数据 要进行合法验证
if(check(chars,x,y,i)){
// 如果合法 那么这种状态已经既定 进行下一次的递归
chars[x][y] = (char) (i+'0');
// 由于是9*9的矩阵 每一行结尾要进行换行 有一个巧妙的算法
// 列数的增量就等于 行数加一再对9进行除法 这样就可以在算完第九个位置的时候 自动开始下一行
// 行数的增量相对简单:加一后对9进行取余即可
dfs(chars,x+(y+1)/9,(y+1)%9);
}
}
// 这个循环走完 还没有找到相应该填的数字说明游戏进行到了死角 之前的某一步走错了 需要走其平行分支
// 所以进行回溯
chars[x][y]='0';
}else {
// 否则这个位置有值那么继续处理下一个位置即可
dfs(chars,x+(y+1)/9,(y+1)%9);
}
}
// 简单的打印二维数据的方法
private static void print(char[][] chars) {
for (int i = 0; i < chars.length; i++) {
System.out.println(Arrays.toString(chars[i]));
}
}
// 检查当前元素是否合法
private static boolean check(char[][] chars, int x, int y, int k) {
for (int i = 0; i <chars[0].length; i++) {
// 判断我这一行有没有k
if(chars[x][i]=='0'+k)
return false;
// 判断我这一列有没有k
if(chars[i][y]=='0'+k)
return false;
}
// 判断九宫格内是否合法
for (int i =(x/3)*3; i <((x/3)*3)+3; i++) {
for (int j = (y/3)*3; j <((y/3)*3)+3; j++) {
if(chars[i][j]=='0'+k)
return false;
}
}
return true;
}
}
测试样例:
030007004
602041000
050030967
040003006
087000350
900700020
718020040
000160809
400500030
总结
其实本算法灵魂的地方是x和y每次在递归中的增量的变化,也就是实现自动换行以及在check()中的检查九宫格是否合法。