JAVA 实现数独

一、数独是什么?

数独是源自18世纪瑞士的一种数学游戏。是一种运用纸、笔进行演算的逻辑游戏。

玩家需要根据9×9盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行、每一列、每一个粗线宫(3*3)内的数字均含1-9,且不重复。

数独盘面是个九宫,每一宫又分为九个小格。在这八十一格中给出一定的已知数字和解题条件,利用逻辑和推理,在其他的空格上填入1-9的数字。使1-9每个数字在每一行、每一列和每一宫中都只出现一次,所以又称“九宫格”。

水平方向有九横行,垂直方向有九纵列的矩形,画分八十一个小正方形,称为九宫格(Grid)。

如图一所示,是数独(Sudoku)的作用范围。

三行与三列相交之处有九格,每一单元称为小九宫(Box、Block),简称宫,如图四所示

二、JAVA实现数独思路分析

1、定义一个9*9的二维数组arr,初始值为默认0;
2、使用for循环,给每个格子填数,这个格子中的数必是1-9中的某一个数字。
如果已经到了最后一行最后一格的下一列,则代表已填数完成。
如果已到了最后一列,则进行新的一行的填数,即 行数+1,列数为第1列。
如果二维数组中元素的值为0,则进入for循环,在循环中使用递归填数,在此过程中,需要排除行、列、宫中已经存在的数字,在剩下的数字中随机选一个。
如果排除掉行、列、宫中的数字后,已经没有可选数字了,说明上一个数填错了,则使用回溯法,还原前一格的数字为0并重新开始填数,直到生成一个可用的数独。

3、第2步,要用到当前位置上是否可以放入数字的判断。
1)当同一列的每一行=要填入的数字时,代表同一列有冲突;
2)当同一行的每一列=要填入的数字时,代表同一行有冲突 ;
3)判断自己所在的宫格内是否有重复数字需要使用for循环
当前格子的行和列分别除以3就代表所在的宫的左上角的行与列。依次循环判断是否与当前要填入的数相等。

三、代码实现

public class Sudoku {
    static int[][] chessNumArr = new int[9][9];
    public static void main(String[] args) {
       setNumber(0,0);
       print();
    }

    public static void setNumber(int i,int j){
        if(i==8 && j==9){ //如果已经到了最后一行最后一格的下一列,则代表已填数完成
            print();
            return;
        }
        if(j==9){ //如果已到了最后一列,则进行新的一行的填数,即 行数+1,列数为第1列
            i++;
            j=0;
        }
        if(chessNumArr[i][j] == 0){
            for(int m=1;m<=9;m++){
                if(judge(i,j,m)){
                    chessNumArr[i][j]=m;
                    setNumber(i,j+1);
                    chessNumArr[i][j]=0; //如果下一格填1-9所有的数字都冲突,则还原前一格的数字为0
                }
            }
        }else {
            setNumber(i,j+1);//如果下一格有数字,则将列数+1,即进入下一格
        }
    }

    //判断当前位置上是否可以放入数字
    public static boolean judge(int row,int col,int val){
         for (int i=0;i<9;i++){
             //判断同一行,同一列是否有重复数字
                if(chessNumArr[row][i] == val || chessNumArr[i][col] == val){
                    return false;
                }
         }

         //判断自己所在的宫格内是否有重复数字
         int tempRow = row/3;
         int tempCol = col/3;
         for(int i=0;i<3;i++){
             for(int j=0;j<3;j++){
                 if(chessNumArr[tempRow*3+i][tempCol*3+j]==val){
                     return false;
                 }
             }
         }
         return true;
    }


    public static void print(){
        for(int i=0;i<9 ;i++){
            for(int j=0;j<9;j++){
                System.out.print(chessNumArr[i][j]+" ");
            }
            System.out.println();
        }
        System.out.println("------------------------------------------------");
    }
}

输出结果有很多种,这里只列举一部分:

------------------------------------------------
1 2 3 4 5 6 7 8 9 
4 5 6 7 8 9 1 2 3 
7 8 9 1 2 3 4 5 6 
2 1 4 3 6 5 8 9 7 
3 6 5 9 7 8 2 1 4 
9 7 8 2 1 4 6 3 5 
5 4 7 8 3 1 9 6 2 
8 3 2 6 9 7 5 4 1 
6 9 1 5 4 2 3 7 8 
------------------------------------------------
1 2 3 4 5 6 7 8 9 
4 5 6 7 8 9 1 2 3 
7 8 9 1 2 3 4 5 6 
2 1 4 3 6 5 8 9 7 
3 6 5 9 7 8 2 1 4 
9 7 8 2 1 4 6 3 5 
5 4 7 8 3 2 9 6 1 
6 9 2 5 4 1 3 7 8 
8 3 1 6 9 7 5 4 2 
------------------------------------------------
1 2 3 4 5 6 7 8 9 
4 5 6 7 8 9 1 2 3 
7 8 9 1 2 3 4 5 6 
2 1 4 3 6 5 8 9 7 
3 6 5 9 7 8 2 1 4 
9 7 8 2 1 4 6 3 5 
5 4 7 8 3 2 9 6 1 
8 3 1 6 9 7 5 4 2 
6 9 2 5 4 1 3 7 8 
------------------------------------------------

 

 

  • 6
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值