2016-04-01 9 views
2

メインでメソッドsolve()への呼び出しが1つしかないSwingクラスをコーディングしました。このメソッドはwhileループを実装し、ほとんどのラウンドで別のメソッドを使用します。このメソッドはpaint()と呼ばれ、参照が2次元配列に格納されている9x9 GridLayoutの内部のJPanelの値を1つだけ変更します。Swingクラスのmainメソッドからのすべての呼び出しでスリープまたは待機する時間

パネルが変更される前に、タイマーはpaint()である必要があります.2秒が経過します。これは最初に呼び出されますが、2秒後にループのすべてのラウンドが待機せずに実行されます。目標は、パネルが変更される前に2秒経過するのを見ることです。私は、javaxタイマーを使用してみました。 Thread.sleep()は明らかにSwingクラスでは機能しません。

import javax.swing.*; 
import javax.swing.Timer; 
import java.awt.*; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.util.*; 
import java.util.Stack; 

public class SudokuApp { 

    private JFrame frame; 
    int i = 9; 
    int j = 9; 
    JPanel[][] board = new JPanel[i][j]; 
    JButton nextButton = new JButton("Resolver"); 
    Box[][] sudoku = new Box[9][9]; 
    Box newCurrent = new Box(); 

    public static void main(String[] args) { 
     EventQueue.invokeLater(new Runnable() { 
      public void run() { 
       try { 
        SudokuApp window = new SudokuApp(); 
        window.frame.setVisible(true); 
       } catch (Exception e) { 
        e.printStackTrace(); 
       } 
      } 
     }); 
    } 

    public SudokuApp() { 
     initialize(); 
    } 

    private void initialize() { 
     frame = new JFrame(); 
     frame.setTitle("Sudoku Solver"); 
     frame.setBounds(100, 100, 510, 555); 
     frame.setLocationRelativeTo(null); 
     frame.setResizable(false); 
     frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 

     JPanel panel = new JPanel(); 
     frame.getContentPane().add(panel, BorderLayout.CENTER); 
     panel.setLayout(new GridLayout(i, j)); 

     //Initiate board 

     for (int m = 0; m < i; m++) { 
      for (int n = 0; n < j; n++) { 
       board[m][n] = new JPanel(); 
       JTextField textField = new JTextField(1); 
       textField.setFont(new Font("Lucida Grande", Font.BOLD, 25)); 
       board[m][n].add(textField); 
       panel.add(board[m][n]); 
      } 
     } 

     Box last = new Box(); 
     for (int m = 0; m < this.i; m++) { 
      for (int n = 0; n < this.j; n++) { 
       sudoku[m][n] = new Box(m, n); 
       if (m != 0 || n != 0) sudoku[m][n].back = last; 
       last = sudoku[m][n]; 
      } 
     } 

     //Solve button action listener 

     nextButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { 
      if (validBoard()) { 
       nextButton.setEnabled(false); 
       solve(); 
      } 
      else JOptionPane.showMessageDialog(null, "Condiciones iniciales inválidas."); 
     } }); 
     frame.getContentPane().add(nextButton, BorderLayout.SOUTH); 
    } 

    private boolean validBoard() { 
     for (int m = 0; m < i; m++) { 
      for (int n = 0; n < j; n++) { 
       JTextField current = (JTextField) board[m][n].getComponent(0); 
       String text = current.getText(); 
       if (text.length() == 1 && !text.contains("0")) { 
        try { 
         int number = Integer.parseInt(text); 
         if (!add(number, m, n)) return false; 
         current.setEditable(false); 
        } catch (NumberFormatException e) { 
         return false; 
        } 
       } else { 
        current.setText(""); 
        current.setEditable(false); 
       } 
      } 
     } 
     return true; 
    } 

    private void solve() { 
     int i = 0; 
     int j = 0; 
     int newI = i + 1; 

     while (i < 9) { 
      while (j < 9) { 
       Box current = sudoku[i][j]; 

       if (current.number == 0) { 
        HashSet<Integer> possibles = new HashSet<>(); 
        HashSet<Integer> takenNumbers = getTakenNumbers(i, j); 
        for (int k = 1; k <= 9; k++) if (!takenNumbers.contains(k)) possibles.add(k); 

        if (possibles.isEmpty()) { 
         current.number = 0; 
         erase(i, j); 
         tryOther(current.back); 

         i = newCurrent.i; 
         newI = i + 1; 
         j = newCurrent.j + 1; 
        } else { 
         for (Integer p : possibles) current.possibles.push(p); 
         current.number = (int) current.possibles.pop(); 

         paint(current.number, i, j); 

         j++; 
         newI = i + 1; 
        } 
       } else { 
        j++; 
        newI = i + 1; 
       } 
      } 
      i = newI; 
      j = 0; 
     } 
    } 

    private void tryOther(Box box) { 
     if (box.possibles.empty()) { 
      if (box.back != null) { 
       if (!box.initial) { 
        box.number = 0; 
        erase(box.i, box.j); 
       } 
       tryOther(box.back); 
      } 
      else newCurrent = null; 
     } else { 
      if (getTakenNumbers(box.i, box.j).contains(box.possibles.peek())) { 
       box.possibles.pop(); 
       tryOther(box); 
      } 
      newCurrent = box; 
      box.number = (int) box.possibles.pop(); 
      paint(box.number, box.i, box.j); 
     } 
    } 

    private boolean add(int a, int i, int j) { 
     if (getTakenNumbers(i, j).contains(a)) return false; 
     sudoku[i][j].number = a; 
     sudoku[i][j].initial = true; 
     return true; 
    } 

    private void paint(int a, int i, int j) { 
     JPanel panel = board[i][j]; 
     JTextField jTextField = (JTextField) board[i][j].getComponent(0); 
     jTextField.setFont(new Font("Lucida Grande", Font.PLAIN, 25)); 
     jTextField.setForeground(Color.gray); 

     ActionListener task = new ActionListener() { 
      public void actionPerformed(ActionEvent e) { 
       System.out.println("T"); 
      } 
     }; 
     Timer timer = new Timer(3000 , task); 
     timer.setRepeats(false); 
     timer.start(); 

     jTextField.setText("" + a); 
     panel.revalidate(); 
     panel.repaint(); 
    } 

    private void erase(int i, int j) { 
     JTextField jTextField = (JTextField) board[i][j].getComponent(0); 
     jTextField.setText(""); 
     board[i][j].revalidate(); 
     board[i][j].repaint(); 
    } 

    private HashSet<Integer> getTakenNumbers(int i, int j) { 
     HashSet<Integer> takenNumbers = new HashSet<>(); 

     for (int k = 0; k < 9; k++) if (sudoku[i][k].number != 0 && k != j) takenNumbers.add(sudoku[i][k].number); 
     for (int k = 0; k < 9; k++) if (sudoku[k][j].number != 0 && k != i) takenNumbers.add(sudoku[k][j].number); 

     int bigBoxRow = 0; 
     int bigBoxColumn = 0; 
     if (i <= 5 && i > 2) bigBoxRow = 3; 
     if (i <= 8 && i > 5) bigBoxRow = 6; 
     if (j <= 5 && j > 2) bigBoxColumn = 3; 
     if (j <= 8 && j > 5) bigBoxColumn = 6; 

     for (int k = bigBoxRow; k < bigBoxRow + 3; k++) for (int l = bigBoxColumn; l < bigBoxColumn + 3; l++) if (sudoku[k][l].number != 0 && k != i && l != j) takenNumbers.add(sudoku[k][l].number); 

     return takenNumbers; 
    } 
} 



import java.util.Stack; 
public class Box { 

    public int number = 0; 
    public int i, j; 
    public Stack possibles = new Stack(); 
    public Box back; 
    public boolean initial = false; 

    public Box(int i, int j) { 
     this.i = i; 
     this.j = j; 
    } 

    public Box() {} 
} 
+0

' 「javax Timerを使用しようとしましたが、使用するアクションリスナーはありません。これは意味をなさないものです。 jTextFieldのテキストを設定するシンプルなActionListenerを作成できないのはなぜですか? –

+0

あなたはそうです、私もそれをやったことがありますが、それはちょうど初めて待っています。更新されたコードを見てください。 – niklabaz

+1

それはうまくいくはずです。そうでない場合は、[mcve]を作成して投稿し、コードをテストしてみましょう。 –

答えて

3

プログラムの構造を変更する必要があります。具体的には、solveメソッド内で入れ子になったwhileループを取り除き、その代わりに単一のSwing Timerで置き換えたいと思うでしょう。そのタイマーは9回9回繰り返され、内部にカウンターフィールドがあり、その中に入れ子のwhileループ内で現在行っているコードを実行したいと思うでしょう。それはのようになります

...遅延でフィールドにテキストを配置します(ただし、何も解決しません)機能プログラムの例については

// TIMER_DELAY could be 2000 if you want a 2 second delay 
    new Timer(TIMER_DELAY, new ActionListener() { 
     private int i = 0; 
     private int j = 0; 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      // MAX_ROWS is 9 
      if (i == MAX_ROWS) { 
       // we've iterated through the whole thing 
       ((Timer) e.getSource()).stop(); 
      } 
      if (j == MAX_ROWS) { 
       // we've gone through all the columns 
       i++; // the next row 
       j = 0; // start at column 0 
      } 
      // TODO the code in the nested while loop. 

      j++; 
     } 
    }).start(); 

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Font; 
import java.awt.GridLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import javax.swing.*; 

public class SudokuMCVE extends JPanel { 
    private static final int CLUSTER = 3; 
    private static final int MAX_ROWS = 9; 
    private static final float FIELD_PTS = 32f; 
    private static final int GAP = 3; 
    private static final Color BG = Color.BLACK; 
    private static final Color SOLVED_BG = Color.LIGHT_GRAY; 
    public static final int TIMER_DELAY = 2 * 1000; 
    private JTextField[][] fieldGrid = new JTextField[MAX_ROWS][MAX_ROWS]; 

    public SudokuMCVE() { 
     JPanel mainPanel = new JPanel(new GridLayout(CLUSTER, CLUSTER)); 
     mainPanel.setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP)); 
     mainPanel.setBackground(BG); 
     JPanel[][] panels = new JPanel[CLUSTER][CLUSTER]; 
     for (int i = 0; i < panels.length; i++) { 
      for (int j = 0; j < panels[i].length; j++) { 
       panels[i][j] = new JPanel(new GridLayout(CLUSTER, CLUSTER, 1, 1)); 
       panels[i][j].setBackground(BG); 
       panels[i][j].setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP)); 
       mainPanel.add(panels[i][j]); 
      } 
     } 

     for (int row = 0; row < fieldGrid.length; row++) { 
      for (int col = 0; col < fieldGrid[row].length; col++) { 
       fieldGrid[row][col] = createField(row, col); 
       int i = row/3; 
       int j = col/3; 
       panels[i][j].add(fieldGrid[row][col]); 
      } 
     } 

     setLayout(new BorderLayout()); 
     add(mainPanel, BorderLayout.CENTER); 
     add(new JButton(new SolveAction("Solve")), BorderLayout.PAGE_END); 
    } 

    private JTextField createField(int row, int col) { 
     JTextField field = new JTextField(2); 
     field.setHorizontalAlignment(JTextField.CENTER); 
     field.setFont(field.getFont().deriveFont(Font.BOLD, FIELD_PTS)); 

     return field; 
    } 

    private class SolveAction extends AbstractAction { 

     public SolveAction(String name) { 
      super(name); 
      int mnemonic = (int) name.charAt(0); 
      putValue(MNEMONIC_KEY, mnemonic); 
     } 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      new Timer(TIMER_DELAY, new ActionListener() { 
       private int i = 0; 
       private int j = 0; 

       @Override 
       public void actionPerformed(ActionEvent e) { 
        // MAX_ROWS is 9 
        if (i == MAX_ROWS) { 
         ((Timer) e.getSource()).stop(); 
        } 
        if (j == MAX_ROWS) { 
         i++; 
         j = 0; 
        } 
        int number = (int) (MAX_ROWS * Math.random()) + 1; 
        fieldGrid[i][j].setBackground(SOLVED_BG); 
        fieldGrid[i][j].setText(String.valueOf(number)); 

        j++; 
       } 
      }).start(); 
     } 
    } 

    private static void createAndShowGui() { 
     SudokuMCVE mainPanel = new SudokuMCVE(); 

     JFrame frame = new JFrame("SudokuMCVE"); 
     frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 
     frame.getContentPane().add(mainPanel); 
     frame.pack(); 
     frame.setLocationByPlatform(true); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(() -> { 
      createAndShowGui(); 
     }); 
    } 
} 
+0

これは、完全な解決方法が完了するまでに決められた時間待つことにはなりませんか?私はあなたが言うことをすることができますが、私はpaint()を呼んでいるときにタイマーを使用するだけですか? – niklabaz

+0

@nxbarz:四角形の間に2秒の遅れで、一度に1つずつ、各四角形を解決します。それはあなたが望むものではありませんか?それを試し、何が起こるか見る。 –

+0

これは私の新しい一時変数では正しく動作しませんか?私はそれを再考すべきですか? – niklabaz

関連する問題