Java破解9X9数独小游戏

news/2024/11/23 2:04:16/

背景

最近刷到LeetCode上这道有趣的题目,想起了初中时候对数独的热爱,不禁感慨万分,原来这个用编程不到1m就能出结果,害我以前还浪费了这么多时间去研究。

效果

据说这是最难的数独题目【点此链接进入】,就拿它开刀吧

初始局面:
8........
..36.....
.7..9.2..
.5...7...
....457..
...1...3.
..1....68
..85...1.
.9....4..开始求解时刻:
2021/06/12 11:59:45答案:
812753649
943682175
675491283
154237896
369845721
287169534
521974368
438526917
796318452结束求解时刻:
2021/06/12 11:59:45耗时:33ms

源代码

一、算法代码:Solution.java

public class Solution {/*** 行*/final int ROW=9;/*** 列*/final int COL=9;/*** 第i行是否填充了value*/boolean [][]row=new boolean[ROW][COL];/*** 第i列是否填充了value*/boolean [][]col=new boolean[ROW][COL];/*** 第i个小九宫是否填充了value*/boolean [][]mid=new boolean[ROW][COL];/*** 数独*/char[][] board;/*** 是否已经得出答案*/boolean solve=false;/*** 求解数独* @param board 数独*/public void solveSudoku(char[][] board) {//初始化三个布尔数组for(int i=0;i<ROW;i++) {for(int j=0;j<COL;j++) {if(board[i][j]=='.') {continue;}else {row[i][board[i][j]-'0'-1]=true;col[j][board[i][j]-'0'-1]=true;mid[i/3*3+j/3][board[i][j]-'0'-1]=true;}}}this.board=board;dfs(0,0);}/*** 深度优先* @param i* @param j*/public void dfs(int i,int j) {//已经解决则不再计算if(solve) {return;}//已经解决的条件if(i>=ROW||j>=COL) {solve=true;return;}//不是空格则无法填数if(board[i][j]!='.') {if(j==COL-1) {dfs(i+1,0);}else {dfs(i,j+1);}return;}//尝试填入1~9,只有没出现过的才能填入,且填入后立即更新已填的布尔数组,事后变回原样for(int number=1;number<=9;number++) {//它是不合法的就跳过if(row[i][number-1]||col[j][number-1]||mid[i/3*3+j/3][number-1]) {continue;//否则尝试填入}else {//尝试填入board[i][j]=(char)(number+48);//更新已填布尔数组row[i][number-1]=true;col[j][number-1]=true;mid[i/3*3+j/3][number-1]=true;//向下一个元素出发//行末处,跳到下一行if(j==COL-1) {dfs(i+1,0);//未到行末,跳到此行下一个元素}else {dfs(i,j+1);}//尝试结束,若没有出结果则重置原样if(solve) {return;}else {board[i][j]='.';row[i][number-1]=false;col[j][number-1]=false;mid[i/3*3+j/3][number-1]=false;}}}}
}

二、测试代码Main.java

import java.text.SimpleDateFormat;
import java.util.Date;public class Main {public static void main(String[] args) {// TODO Auto-generated method stubchar[][]board=new char[9][9];//String value="530070000\n600195000\n098000060\n800060003\n400803001\n700020006\n060000280\n000419005\n000080079";String value="800000000\n003600000\n070090200\n050007000\n000045700\n000100030\n001000068\n008500010\n090000400";String []rows=value.split("\n");for(int i=0;i<rows.length;i++) {for(int j=0;j<rows[i].length();j++) {board[i][j]=rows[i].charAt(j);if(board[i][j]=='0') {board[i][j]='.';}}}System.out.println("初始局面:");display(board);SimpleDateFormat sdf=new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");Date start=new Date();System.out.println();System.out.println("开始求解时刻:");System.out.println(sdf.format(start));long s=System.currentTimeMillis();Solution solution=new Solution();solution.solveSudoku(board);System.out.println();System.out.println("答案:");display(board);System.out.println();Date end=new Date();System.out.println("结束求解时刻:");System.out.println(sdf.format(end));System.out.println();long e=System.currentTimeMillis();System.out.println("耗时:"+(e-s)+"ms");}public static void display(char[][] board) {for(int i=0;i<9;i++) {for(int j=0;j<9;j++) {System.out.print(board[i][j]);}System.out.println();}}
}

算法思路

        让电脑模拟人的思维,根据数独规则,每行、列、小九宫内数字1-9能且仅能出现一次。根据此规则,我们可以定义三个哈希数组来存储这三种情况。

        布尔数组row,给它九行九列,让row[i][number]来表示i+1行是否出现过number+1【注意计算机的数组下标从零开始,当然你可以根据习惯舍弃第0行列而从1开始】。

        布尔数组col,给它九行九列,让col[i][number]来表示i+1列是否出现过number+1【注意计算机的数组下标从零开始,当然你可以根据习惯舍弃第0行列而从1开始】。

        布尔数组mid,给它九行九列,让mid[i][number]来表示i+1个小九宫是否出现过number+1【注意计算机的数组下标从零开始,当然你可以根据习惯舍弃第0行列而从1开始】。

        拿到题目时我们先根据给出的信息,填充好我们设定的三个布尔数组。紧接着就是我们万能破解尝试类游戏的模板之一:深度优先搜索,为了将程序写的简单,我们使用递归写法。为了同学们这里少采坑,我总结了一下四条经验【我们从第1行开始,一行一行地去尝试填数。函数原型:f(i,j),表示当前尝试的元素是i+1行、j+1列的】。

        1.设置哨兵[布尔类型],作为求解结束的标志,即得出一个结果时,通知递归函数跳出。

        2.当尝试的行列超出了9,说明求出结果了,哨兵至true,跳出递归。

        3.当前元素已经填过了,那就跳过它,尝试下一个元素

        4.当前元素没有填过,将可能的值填入,并更新表示已填的那三个布尔数组,尝试下一个元素。如果尝试完成后问题解决了,就退出递归函数,否则就重置刚刚的状态:包括局面和三个布尔数组。


http://www.ppmy.cn/news/563453.html

相关文章

C语言数独游戏求解

数独游戏的解法&#xff1a; 先将数独分为九个格子&#xff0c;用一个数组将每个小九宫格的候选数存放下来&#xff0c;将候选数挨个放进数独里的空位&#xff0c;如果这一行和这一列都没有这个数字&#xff0c;继续放入下一个&#xff0c;如果不能放入的话就回到上一步继续尝…

POJ2676数独游戏题解

第三次才AC我好菜 一道“简单”的问题。 Description Sudoku is a very simple task. A square table with 9 rows and 9 columns is divided to 9 smaller squares 3x3 as shown on the Figure. In some of the cells are written decimal digits from 1 to 9. The other c…

python解数独--世界最难数独2.3秒完成

“芬兰数学家因卡拉&#xff0c;花费3个月时间设计出了世界上迄今难度最大的数独游戏&#xff0c;而且它只有一个答案。因卡拉说只有思考能力最快、头脑最聪明的人才能破解这个游戏。”这是英国《每日邮报》2012年6月30日的一篇报道。看完这个新闻就对数独有点感兴趣了&#xf…

puzzle(0111)《数独》

目录 一&#xff0c;标准数独&#xff08;规则数独&#xff09; 1&#xff0c;规则 2&#xff0c;隐含规则 3&#xff0c;对称性 4&#xff0c;斜线数独 二&#xff0c;标准数独校验、求解 力扣 36. 有效的数独 POJ 3074 Sudoku POJ 2676 Sudoku HDU 1426 Sudoku Kil…

数独解题器强化版

经过实际测试&#xff0c;在解决高难度数独时&#xff0c;解题器的效果仍旧不理想&#xff0c;所以添加了数字提示功能。 另外添加了自定义数独数据功能。 MainWindow.xaml <Window x:Class"SudokuSolver.MainWindow"xmlns"http://schemas.microsoft.com/…

【开源】完美破解九宫格(数独)游戏

数独是一种比较费时费脑的游戏&#xff0c;一般难度的数独玩下来也得1个小时左右&#xff0c;本人是伪数独爱好者&#xff0c;碰到难点的数独需要花上若干个小时&#xff0c;于是偷懒写了一套破解程序&#xff0c;特拿出来分享&#xff0c;希望有人喜欢。 思路&#xff1a; 1、…

经典数独游戏+数独求解器—纯C语言实现

“心常乐数独小游戏”&#xff08;以下简称“本软件”&#xff09;是一款windows平台下的数独游戏软件。 本软件是开源、免费软件。 本软件使用纯C语言编写&#xff0c;MinGW编译&#xff0c;NSIS打包。 本软件主要特性如下&#xff1a; 支持“闯关模式”和“选关模式” 支…

python实现简易数独小游戏

起源 既然“数独”有一个字是“数”&#xff0c;人们也往往会联想到数学&#xff0c;那就不妨从大家都知道的数学家欧拉说起&#xff0c;但凡想了解数独历史的玩家在网络、书籍中搜索时&#xff0c;共同会提到的就是欧拉的“拉丁方块&#xff08;Latin square&#xff09;”。…