java数独问题的分析

img


给两个正整数通过条件来生成一个数独题目,该如何让数独数据随机呢,求解给出代码

代码里面有详细注释,我这个设定了初始化n和m都为9,你可以自己选择输入或固定,看看能不能满足需求


import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;

public class Main {

    public static void main(String[] args) {
        int n = 9; // 数独的维度
        int m = 9; // 空缺数字的格点数目

        int[][] sudoku = generateSudoku(n, m);
        printSudoku(sudoku);
    }

    // 生成数独题目
    public static int[][] generateSudoku(int n, int m) {
        int[][] sudoku = new int[n][n];

        // 初始化数独
        initializeSudoku(sudoku, n);

        // 随机将一些格点设置为空缺
        Random random = new Random();
        int count = 0;
        while (count < m) {
            int row = random.nextInt(n);
            int col = random.nextInt(n);
            if (sudoku[row][col] != 0) {
                sudoku[row][col] = 0;
                count++;
            }
        }

        return sudoku;
    }

    // 初始化数独(填充每一行)
    public static void initializeSudoku(int[][] sudoku, int n) {
        for (int row = 1; row <= n; row++) {
            List<Integer> nums = new ArrayList<>();
            for (int num = 1; num <= n; num++) { //初始化时就是for循环从1到n依次填入列表中(这样可以保证这一列数据是不会出现重复的),后面在打乱
                nums.add(num);
            }
            Collections.shuffle(nums); //这个方法就是用于随机打乱顺序的

            for (int col = 0; col < n; col++) {
                sudoku[row - 1][col] = nums.get(col);
            } //这段代码是将打乱顺序后的数字列表 nums 中的元素按顺序放进那个二维数组中)。
        }
    }

    // 打印数独
    public static void printSudoku(int[][] sudoku) {
        int n = sudoku.length;
        for (int row = 0; row < n; row++) {
            for (int col = 0; col < n; col++) {
                System.out.print(sudoku[row][col] + " ");
            }
            System.out.println();
        }
    }
}
import java.util.Scanner;
public class Shudu {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        System.out.print("请输入n:");
        int n = input.nextInt();
        System.out.print("请输入m:");
        int m = input.nextInt();

        // 初始化数独矩阵
        int[][] matrix = new int[n][n];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                matrix[i][j] = 0;
            }
        }

        // 随机填充m个数字
        for (int k = 0; k < m; k++) {
            int i, j, num;
            do {
                i = (int) (Math.random() * n);
                j = (int) (Math.random() * n);
                num = (int) (Math.random() * n) + 1;
            } while (!isValid(matrix, i, j, num));
            matrix[i][j] = num;
        }

        // 输出数独题目
        System.out.println();
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                if (matrix[i][j] == 0) {
                    System.out.print("_ ");
                } else {
                    System.out.print(matrix[i][j] + " ");
                }
            }
            System.out.println();
        }
    }

    // 判断在给定位置填入给定数字是否合法
    private static boolean isValid(int[][] matrix, int row, int col, int num) {
        // 判断行是否合法
        for (int j = 0; j < matrix.length; j++) {
            if (matrix[row][j] == num) {
                return false;
            }
        }

        // 判断列是否合法
        for (int i = 0; i < matrix.length; i++) {
            if (matrix[i][col] == num) {
                return false;
            }
        }

        // 判断宫是否合法
        int sqrtN = (int) Math.sqrt(matrix.length);
        int boxRowStart = row - row % sqrtN;
        int boxColStart = col - col % sqrtN;

        for (int r = boxRowStart; r < boxRowStart + sqrtN; r++) {
            for (int c = boxColStart; c < boxColStart + sqrtN; c++) {
                if (matrix[r][c] == num) {
                    return false;
                }
            }
        }

        return true;
    }
}
您好,我是有问必答小助手,您的问题已经有小伙伴帮您解答,感谢您对有问必答的支持与关注!
PS:问答VIP年卡 【限时加赠:IT技术图书免费领】,了解详情>>> https://vip.csdn.net/askvip?utm_source=1146287632
  • 你可以看下这个问题的回答https://ask.csdn.net/questions/7566573
  • 这篇博客也不错, 你可以看下Java实现字符串相似度算法,用于试题相似度,字符串相似度,字符串比较等场景
  • 你还可以看下java参考手册中的 java-集合 - 关于使用和扩展Java集合框架的课程。- 聚合操作 代表你对集合进行迭代,这使你能够编写更简洁和有效的代码,处理存储在集合中的元素。 -平行主义
  • 除此之外, 这篇博客: java异常初理解中的 异常处理使得程序可以处理非预期的情景,并且继续正常的处理。 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
  •  在这个世界不可能存在完美的东西,不管完美的思维有多么缜密,细心,我们都不可能考虑所有的因素,这就是所谓的智者千虑必有一失。同样的道理,计算机的世界也是不完美的,异常情况随时都会发生,我们所需要做的就是避免那些能够避免的异常,处理那些不能避免的异常。这里我将记录如何利用异常还程序一个“完美世界”。

    异常处理最根本的优势就是将检测错误(由被调用的方法完成)从处理错误(由调用方法完成)中分离出来。(也就是没有那么多if语句了)

  • 您还可以看一下 汪翠老师的java项目实战之欢乐斗地主游戏开发教程 毕业项目课程设计带源码课程中的 创建服务器端接收客户端上线消息小节, 巩固相关知识点
  • 以下回答由chatgpt基于相关博客总结生成:

    首先,生成随机数独题目的代码需要了解数独的规则和生成算法。以下是一个简单的数独生成算法的解决方案:

    import java.util.Random;
    
    public class SudokuGenerator {
        private int[][] board;
    
        public SudokuGenerator() {
            board = new int[9][9];
        }
    
        public int[][] generate() {
            // 使用回溯算法生成数独
            generateSudoku(board, 0, 0);
            return board;
        }
    
        private boolean generateSudoku(int[][] board, int row, int col) {
            // 到达最后一行,结束递归
            if (row == 9) {
                return true;
            }
    
            // 到达当前行的最后一个列,进入下一行
            if (col == 9) {
                return generateSudoku(board, row + 1, 0);
            }
    
            // 如果当前位置已有值,进入下一个位置
            if (board[row][col] != 0) {
                return generateSudoku(board, row, col + 1);
            }
    
            // 随机生成一个候选数字列表
            int[] candidates = new int[9];
            for (int i = 0; i < 9; i++) {
                candidates[i] = i + 1;
            }
            shuffleArray(candidates);
    
            // 尝试填充候选数字,递归调用进行下一步尝试
            for (int num : candidates) {
                if (isValid(board, row, col, num)) {
                    board[row][col] = num;
                    if (generateSudoku(board, row, col + 1)) {
                        return true;
                    }
                    board[row][col] = 0;
                }
            }
    
            return false;
        }
    
        private boolean isValid(int[][] board, int row, int col, int num) {
            // 判断当前数字在当前行是否重复
            for (int c = 0; c < 9; c++) {
                if (board[row][c] == num) {
                    return false;
                }
            }
    
            // 判断当前数字在当前列是否重复
            for (int r = 0; r < 9; r++) {
                if (board[r][col] == num) {
                    return false;
                }
            }
    
            // 判断当前数字在当前3x3方格内是否重复
            int startRow = (row / 3) * 3;
            int startCol = (col / 3) * 3;
            for (int r = startRow; r < startRow + 3; r++) {
                for (int c = startCol; c < startCol + 3; c++) {
                    if (board[r][c] == num) {
                        return false;
                    }
                }
            }
    
            return true;
        }
    
        private void shuffleArray(int[] array) {
            Random random = new Random();
            for (int i = array.length - 1; i > 0; i--) {
                int j = random.nextInt(i + 1);
                int temp = array[i];
                array[i] = array[j];
                array[j] = temp;
            }
        }
    }
    

    以上代码通过回溯算法生成数独,使用了递归的思想。具体解决方案如下:

    1. 创建一个名为SudokuGenerator的类。
    2. 在该类中,定义一个9x9的整型数组board作为数独题目的容器。
    3. 创建一个无参构造方法,在构造方法中初始化board数组。
    4. 创建一个公有方法generate(),该方法将返回生成的数独题目的数组。
    5. 在generate()方法中,调用内部私有方法generateSudoku(),并传入board和初始的行和列(0,0)。
    6. 在generateSudoku()方法中,添加递归终止条件,如果递归到达最后一行,返回true。
    7. 在generateSudoku()方法中,添加递归终止条件,如果递归到达当前行的最后一个列,进入下一行。
    8. 在generateSudoku()方法中,添加递归终止条件,如果当前位置已有值,进入下一个位置。
    9. 在generateSudoku()方法中,生成一个候选数字列表,使用shuffleArray()方法对候选数字进行随机排序。
    10. 在generateSudoku()方法中,遍历候选数字列表,尝试填充数字并进行下一步尝试。
    11. 在generateSudoku()方法中,调用isValid()方法判断填充的数字是否有效。
    12. 在isValid()方法中,判断数字在当前行、当前列和当前3x3方格内是否重复。
    13. 如果填充的数字有效,将数字填充到board数组中,并递归执行generateSudoku()方法。
    14. 如果递归返回true,表示生成成功,返回true。
    15. 如果当前位置的数字填充不满足条件,将该位置的数字置为0,并返回false。
    16. 返回generate()方法中的board数组作为生成的数独题目。

    使用以上的Java代码实现一个随机数独生成器,可以根据自己的需求进行适当的调整和拓展。