4

数独関連の質問についてはすでにいくつかの投稿がありますが、どれも私が探しているものを正確に持っているかどうかはわかりません...

JPanelsとJTextfieldsを使用してJavaで空の数独ボードを作成しようとしています。また、右側に別のJPanelでメニューを作成する必要があります。

ボード自体は9x9の正方形で、93x3の正方形に分割されています。それぞれの小さい正方形は、通常の正方形間の境界よりも重い境界で区切られていることに注意してください。各正方形はテキストフィールドです。テキストフィールドに何も入力されないようにプログラムを作成します。ユーザーは必要に応じてテキストフィールドに入力でき、入力すると数字が表示されます。側面には、解く、新しいパズルを取得する、ヒントを取得する、またはパズルをリセットするための4つのボタンがあります。

どんなアイデアでも素晴らしいでしょう。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

私が見るいくつかのこと:

  • 今のように9x9が必要だとは思いませんJPanelが、9x9が必要ですJTextFieldJPanel各セクションの境界線を太くすることができるように、3x3が必要な場合があります。ループで実行するよりも、これらを明示的にレイアウトする方が簡単な場合があります。

  • ループカウンター(および配列インデックス)は、1ではなく0から開始する必要があります。現在のように、ループは8回しか実行されません。

  • 各行、列、および各3x3サブグループの値を追跡する必要があります。行と列は、2D配列の場合と同じように簡単です。各3x3領域の値を保持する配列の別の配列を検討することもできます。これにより、必要なときにこれらの値をスキャンしやすくなり、JPanelそのルートを使用する場合は、小さい3x3に値を配置するのに役立つ場合があります。

于 2012-10-14T20:41:56.203 に答える
5

まず、ある種のモデルを使用して「仮想」ボード内の値を制御します。これにより、ロジックがUIから分離され、どちらかが他方に悪影響を与えることなく変更できるようになります。

モデルに適切なイベントを提供して、モデルが変更されたときにUIを更新できるようにするとともに、各フィールドが必要に応じてモデルを更新する手段を提供します。

次に、問題を最小の概念コンポーネントであるサブボードに減らし、可能な限り最も抽象的な方法でそれを表すUIを生成します。これにより、1つのボードに問題があるかのように再利用でき、デバッグに役立ちます。その後、すべてのボードを1か所で修正できます。

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アレイを使用)

これは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 に答える