4

我知道已经有几篇关于数独相关问题的帖子,但我不确定其中是否有我正在寻找的内容......

我正在尝试使用 JPanels 和 JTextfields 在 Java 中构建一个空的数独板。我还需要使用另一个 JPanel 在右侧创建一个菜单。

棋盘本身是一个 9 x 9 的正方形,分成 9 个 3x3 的正方形。请注意,每个较小的正方形都由比常规正方形间边界更重的边界隔开。每个方块都是一个文本字段。编写程序,使文本字段中没有任何内容。用户可以根据需要在文本字段中输入,如果输入,数字将显示出来。侧面有四个按钮,可让您解决、获得新谜题、获得提示或重置谜题。

任何想法都会很棒。我无法理解如何嵌套 for 循环来创建板。这是我的代码...

    import javax.swing.*;
    import javax.swing.border.Border;
    import java.awt.*;

    public class ArrayTest extends JFrame {

        public ArrayTest() {

    JPanel board = new JPanel(new GridLayout(9, 9));
    add(board);

    JPanel[][] squares = new JPanel[9][9];

    Border border = BorderFactory.createLineBorder(Color.BLACK);


    for (int row = 1; row < 9; row++) {

        for (int col = 1; col < 9; col++) {
            squares[row][col] = new JPanel();
            board.add(squares[row][col]);

        }

    }



    JPanel menu = new JPanel();
    menu.add(new JButton("Reset"));
    menu.add(new JButton("Hint"));
    menu.add(new JButton("Solve"));
    menu.add(new JButton("New Puzzle"));



    add(menu);

}
public static void main(String[] args) {
    // TODO Auto-generated method stub

    /** Create a frame and set its properties*/
    JFrame frame = new ArrayTest();
    frame.setTitle("Sudoku");
    frame.setSize(600, 600);
    frame.setLocationRelativeTo(null); //Center the frame
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setVisible(true);

}

}

4

2 回答 2

6

我看到的几件事:

  • 我不认为你JPanel现在想要 9x9 s,而是 9x9 JTextFields。您可能需要 3x3 JPanels,以便您可以使每个部分的边框更粗。明确地布置这些而不是尝试在循环中进行可能更容易。

  • 您的循环计数器(和数组索引)应该从 0 开始,而不是 1。按照您现在的方式,循环只会执行 8 次。

  • 您将要跟踪每行、每列和每个 3x3 子组中的值。行和列很简单,就像您在 2D 数组中一样。您可能会考虑使用另一个数组来保存每个 3x3 区域中的值。JPanel这使您在需要时更容易扫描这些值,并且如果您走这条路,可能有助于将值放置在较小的 3x3中。

于 2012-10-14T20:41:56.203 回答
5

首先,我会使用某种模型来控制“虚拟”板中的值,这会将逻辑与 UI 分开,并允许其中一个进行更改而不会对另一个产生不利影响。

我会为模型提供适当的事件,以允许在模型更改时更新 UI,并为每个字段提供一种根据需要更新模型的方法。

然后,我会将问题简化为最小的概念组件,即子板,并生成 UI 以尽可能抽象的方式表示它。这允许重复使用并有助于调试,就好像一块板有问题,然后你可以在一个地方修复它。

public class Sudoku {

    public static void main(String[] args) {
        new Sudoku();
    }

    public Sudoku() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException ex) {
                } catch (InstantiationException ex) {
                } catch (IllegalAccessException ex) {
                } catch (UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new SudokuBoard());
                frame.add(new MenuPane(), BorderLayout.AFTER_LINE_ENDS);
                frame.pack();
                frame.setVisible(true);
            }
        });
    }

    public class MenuPane extends JPanel {

        public MenuPane() {
            setBorder(new EmptyBorder(4, 4, 4, 4));
            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridx = 0;
            gbc.gridy = 1;
            gbc.weightx = 1;
            gbc.fill = GridBagConstraints.HORIZONTAL;

            add(new JButton("Solve"), gbc);
            gbc.gridy++;
            add(new JButton("New"), gbc);
            gbc.gridy++;
            add(new JButton("Hint"), gbc);
            gbc.gridy++;
            add(new JButton("Reset"), gbc);
        }
    }

    public class SudokuBoard extends JPanel {

        public static final int ROWS = 3;
        public static final int COLUMNS = 3;

        private SubBoard[] subBoards;

        public SudokuBoard() {
            setBorder(new EmptyBorder(4, 4, 4, 4));
            subBoards = new SubBoard[ROWS * COLUMNS];
            setLayout(new GridLayout(ROWS, COLUMNS, 2, 2));
            for (int row = 0; row < ROWS; row++) {
                for (int col = 0; col < COLUMNS; col++) {
                    int index = (row * ROWS) + col;
                    SubBoard board = new SubBoard();
                    board.setBorder(new CompoundBorder(new LineBorder(Color.GRAY, 3), new EmptyBorder(4, 4, 4, 4)));
                    subBoards[index] = board;
                    add(board);
                }
            }
        }
    }

    public class SubBoard extends JPanel {

        public static final int ROWS = 9;
        public static final int COLUMNS = 9;

        private JTextField[] fields;

        public SubBoard() {
            setLayout(new GridLayout(ROWS, COLUMNS, 2, 2));
            fields = new JTextField[ROWS * COLUMNS];
            for (int row = 0; row < ROWS; row++) {
                for (int col = 0; col < COLUMNS; col++) {
                    int index = (row * COLUMNS) + col;
                    JTextField field = new JTextField(4);
                    fields[index] = field;
//                    field.setText(Integer.toString(index));
                    add(field);
                }
            }
        }
    }
}

更新

要将文本字段限制为仅允许输入数字值,您可以查看JTextField 限制字符量输入和仅接受数字的一些想法

在此处输入图像描述

更新(使用二维数组)

这是一个使用 2D 数组的实现,它还对子板进行分组,以便每个 3x3 字段的网格都有自己的板...

在此处输入图像描述

public class Sudoku {

    public static void main(String[] args) {
        new Sudoku();
    }

    public Sudoku() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException ex) {
                } catch (InstantiationException ex) {
                } catch (IllegalAccessException ex) {
                } catch (UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new SudokuBoard());
                frame.add(new MenuPane(), BorderLayout.AFTER_LINE_ENDS);
                frame.pack();
                frame.setVisible(true);
            }
        });
    }

    public class MenuPane extends JPanel {

        public MenuPane() {
            setBorder(new EmptyBorder(4, 4, 4, 4));
            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridx = 0;
            gbc.gridy = 1;
            gbc.weightx = 1;
            gbc.fill = GridBagConstraints.HORIZONTAL;

            add(new JButton("Solve"), gbc);
            gbc.gridy++;
            add(new JButton("New"), gbc);
            gbc.gridy++;
            add(new JButton("Hint"), gbc);
            gbc.gridy++;
            add(new JButton("Reset"), gbc);

        }

    }

    public class SudokuBoard extends JPanel {

        public static final int ROWS = 3;
        public static final int COLUMNS = 3;

        private SubBoard[][] subBoards;

        public SudokuBoard() {
            setBorder(new EmptyBorder(4, 4, 4, 4));
            subBoards = new SubBoard[ROWS][COLUMNS];
            setLayout(new GridLayout(ROWS, COLUMNS, 2, 2));
            for (int row = 0; row < ROWS; row++) {
                for (int col = 0; col < COLUMNS; col++) {
                    int index = (row * ROWS) + col;
                    SubBoard board = new SubBoard();
                    board.setBorder(new CompoundBorder(new LineBorder(Color.GRAY, 3), new EmptyBorder(4, 4, 4, 4)));
                    subBoards[row][col] = board;
                    add(board);
                }
            }
        }

    }

    public class SubBoard extends JPanel {

        public SubBoard() {
            setLayout(new GridLayout(3, 3, 2, 2));

            for (int index = 0; index < 3*3; index++) {
                add(new ChildBoard(3, 3));
            }

        }
    }

    public class ChildBoard extends JPanel {

        private JTextField[][] fields;

        public ChildBoard(int rows, int cols) {
            setBorder(new LineBorder(Color.LIGHT_GRAY));
            setLayout(new GridLayout(rows, cols, 2, 2));
            fields = new JTextField[rows][cols];
            for (int row = 0; row < rows; row++) {
                for (int col = 0; col < cols; col++) {
                    JTextField field = new JTextField(4);
                    fields[row][col] = field;
                    add(field);
                }
            }
        }

    }
}

或者,如果您想尝试将所有字段保留在一个顶级引用中,您可以执行类似...

public class SubBoard extends JPanel {

    private JTextField[][] fields;

    public SubBoard() {
        setLayout(new GridLayout(3, 3, 2, 2));

        fields = new JTextField[9][9];
        for (int row = 0; row < 9; row++) {
            for (int col = 0; col < 9; col++) {
                fields[row][col] = new JTextField(4);
            }
        }

        for (int row = 0; row < 3; row++) {
            for (int col = 0; col < 3; col++) {

                int startRow = row * 3;
                int startCol = col * 3;

                add(new ChildBoard(3, 3, fields, startRow, startCol));

            }
        }

    }
}

public class ChildBoard extends JPanel {

    public ChildBoard(int rows, int cols, JTextField[][] fields, int startRow, int startCol) {
        setBorder(new LineBorder(Color.LIGHT_GRAY));
        setLayout(new GridLayout(rows, cols, 2, 2));
        for (int row = 0; row < rows; row++) {
            for (int col = 0; col < cols; col++) {
                JTextField field = fields[startRow + row][startCol + col];
                fields[row][col] = field;
                add(field);
            }
        }
    }

}

更新单类

好吧,与其子分类,不如简单地使用几种方法来创建板的每个单独部分,您可以从中重复调用...

在此处输入图像描述

记住,减少和重用。

public class Sudoku {

    public static void main(String[] args) {
        new Sudoku();
    }

    public Sudoku() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException ex) {
                } catch (InstantiationException ex) {
                } catch (IllegalAccessException ex) {
                } catch (UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new SudokuBoard());
                frame.add(new MenuPane(), BorderLayout.AFTER_LINE_ENDS);
                frame.pack();
                frame.setVisible(true);
            }
        });
    }

    public class MenuPane extends JPanel {

        public MenuPane() {
            setBorder(new EmptyBorder(4, 4, 4, 4));
            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridx = 0;
            gbc.gridy = 1;
            gbc.weightx = 1;
            gbc.fill = GridBagConstraints.HORIZONTAL;

            add(new JButton("Solve"), gbc);
            gbc.gridy++;
            add(new JButton("New"), gbc);
            gbc.gridy++;
            add(new JButton("Hint"), gbc);
            gbc.gridy++;
            add(new JButton("Reset"), gbc);

        }
    }

    public class SudokuBoard extends JPanel {

        public static final int GRID_ROWS = 3;
        public static final int GRID_COLUMNS = 3;
        public static final int BOARD_ROWS = 9;
        public static final int BOARD_COLUMNS = 9;
        private JTextField fields[][];

        public SudokuBoard() {
            setBorder(new EmptyBorder(4, 4, 4, 4));
            fields = new JTextField[GRID_ROWS * BOARD_ROWS][GRID_COLUMNS * BOARD_COLUMNS];

            setLayout(new GridLayout(GRID_ROWS, GRID_COLUMNS, 2, 2));
            for (int row = 0; row < GRID_ROWS; row++) {
                for (int col = 0; col < GRID_COLUMNS; col++) {
                    int startRow = row * GRID_ROWS;
                    int startCol = col * GRID_COLUMNS;
                    add(createBoard(fields, startRow, startCol));
                }
            }
        }

        protected JPanel createBoard(JTextField fiels[][], int startRow, int startCol) {
            JPanel panel = new JPanel(new GridLayout(3, 3, 2, 2));
            panel.setBorder(new CompoundBorder(new LineBorder(Color.DARK_GRAY, 2), new EmptyBorder(2, 2, 2, 2)));

            for (int row = 0; row < 3; row++) {
                for (int col = 0; col < 3; col++) {
                    int rowIndex = (startRow + row) * 3;
                    int colIndex = (startCol + col) * 3;
                    panel.add(createSubBoard(fields, rowIndex, colIndex));
                }
            }
            return panel;
        }

        protected JPanel createSubBoard(JTextField[][] fields, int startRow, int startCol) {
            JPanel panel = new JPanel(new GridLayout(3, 3, 2, 2));
            panel.setBorder(new CompoundBorder(new LineBorder(Color.GRAY, 2), new EmptyBorder(2, 2, 2, 2)));

            populateFields(fields, startRow, startCol);
            for (int row = 0; row < 3; row++) {
                for (int col = 0; col < 3; col++) {
                    panel.add(fields[row + startRow][col + startCol]);
                }
            }
            return panel;
        }

        protected void populateFields(JTextField[][] fields, int startRow, int startCol) {
            for (int row = startRow; row < startRow + 3; row++) {
                for (int col = startCol; col < startCol + 3; col++) {
                    fields[row][col] = new JTextField(4);
                }
            }
        }
    }
}
于 2012-10-15T02:10:12.737 回答