回溯法解数独游戏问题

2022-10-20 14:26:53

1.数独游戏:九宫格是在81个格子(9×9)中,要满足以下条件:① 每个横行和竖列中的9个格子都包含数字1~9,且不重复;② 每个黑色粗实线围住的9个格子(3×3)都包含数字1~9,且不重复。如图所示:

要求:找出给定数字的九宫格。

输入:输入9行9列81个数字,其中0表示要填的数字。

输出:输出满足条件的九宫格。

某测试样例如下:

输  入

输  出

0 6 1 0 3 0 0 2 0

0 5 0 0 0 8 1 0 7

0 0 0 0 0 7 0 3 4

0 0 9 0 0 6 0 7 8

0 0 3 2 0 9 5 0 0

5 7 0 3 0 0 9 0 0

1 9 0 7 0 0 0 0 0

8 0 2 4 0 0 0 6 0

0 4 0 0 1 0 2 5 0

7 6 1 9 3 4 8 2 5

3 5 4 6 2 8 1 9 7

9 2 8 1 5 7 6 3 4

2 1 9 5 4 6 3 7 8

4 8 3 2 7 9 5 1 6

5 7 6 3 8 1 9 4 2

1 9 5 7 6 2 4 8 3

8 3 2 4 9 5 7 6 1

6 4 7 8 1 3 2 5 9


import java.util.Scanner;

public class 数独游戏 {

	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int n = 9;
		int Sudoku[][] = new int[n][n];
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++)
				Sudoku[i][j] = in.nextInt();
		}
		backTrack(Sudoku, n * n, 0);//其中n*n,每一个单元格表示一层深度
	}

	static void backTrack(int[][] Sudoku, int N, int k) {//数独棋盘元素数组,最大单元格数,当前单元格数
		int x = k / 9;//0,0,0,0,0,0,0,0,0, 1,1,1,1...
		int y = k % 9;//0,1,2,3,4,5,6,7,8, 0,1,2,3...
		//由此遍历所有数独单元格
		if (k == N) {//搜索完毕,输出结果
			for (int i = 0; i < 9; i++) {
				for (int j = 0; j < 9; j++) {
					System.out.print(Sudoku[i][j]+" ");
				}
				System.out.println();
			}
			return;
		}
		if (Sudoku[x][y] == 0) {//表示此单元格未填写
			for (int i = 1; i <= 9; i++) {//每个空格有0~9,9种可能
				Sudoku[x][y] = i;//逐个测试
				if (constraint1(Sudoku, x, y) && constraint2(Sudoku, x, y)) {//如果满足约束条件
					backTrack(Sudoku, N, k + 1);//才能深度搜索到下一个单元格
				}
				else { //不满足约束条件
					Sudoku[x][y] = 0;//回溯法将上一个单元格重置为0				
				}
			}
		} 
		else {//表示此单元格已填写,深度搜索下一个单元格
			backTrack(Sudoku, N, k + 1);
		}
	}

	private static boolean constraint1(int[][] Sudoku, int x, int y) {
		for (int i = 0; i < 9; i++) {
			if (Sudoku[x][i] == Sudoku[x][y] && i != y) {//搜索每一列中是否有重复数值
				return false;
			}
			if (Sudoku[i][y] == Sudoku[x][y] && i != x) {//搜索每一行中是否有重复数值
				return false;
			}
		}
		return true;
	}

	private static boolean constraint2(int[][] Sudoku, int x, int y) {
		for (int i = (x / 3) * 3; i < (x / 3) * 3 + 3; i++) {//九宫格中行的约束条件((x / 3) * 3为九宫格第一行,加3为最后一行)
			for (int j = (y / 3) * 3; j < (y / 3) * 3 + 3; j++) {//九宫格中列的约束条件((y / 3) * 3为九宫格第一列,加3为最后一列)
				if (Sudoku[i][j] == Sudoku[x][y]) {//出现重复数值
					if (i != x && j != y) {//不满足约束条件
						return false;						
					}
					else {
						continue;						
					}
				}
			}
		}
		return true;
	}
}

  • 作者:友人CWH
  • 原文链接:https://blog.csdn.net/CWH0908/article/details/80247318
    更新时间:2022-10-20 14:26:53