Also bevor ich bisschen Code poste schildere ich mein Problem. Ich schreibe als kleine Übung ein Programm, dass Sudokus lösen kann. Ich habe zwei Klassen.
Die eine ist die Main-class in der Main.java. In ihr geschieht das Lösen des Sudokus. Das klappt alles super.
Die zweite ist die GUI-class in der GUI.java. In ihr modelliere ich halt das GUI. 9x9 Textfields und ein Button zum Starten des Ganzen.
Das Programm liest die Textfields aus(wenn beschriftet) und gibt diese an die Main.java weiter und dort geschieht dann der Rest. Zum Schluss rufe ich die Methode writeSudoku(array) auf, welche sich ebenfalls in der GUI.java befindet und die Textfelder nun mit der Lösung beschriften soll.
GUI.java:
Code:
import java.awt.BorderLayout; import java.awt.EventQueue; import java.awt.*; import java.awt.event.*; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.border.EmptyBorder; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JSplitPane; import javax.swing.JScrollPane; import javax.swing.JTextField; import java.awt.Color; public class GUI extends JFrame { private JPanel contentPane; private JTextField[][] allField = new JTextField[9][9]; //IMPORTANT!!!: first [] here is the column and second [] the row!!! /** * Launch the application. */ public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { public void run() { try { GUI frame = new GUI(); frame.setVisible(true); } catch (Exception e) { e.printStackTrace(); } } }); } /** * Create the frame. */ public GUI() { setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setBounds(100, 100, 310, 362); contentPane = new JPanel(); contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); setContentPane(contentPane); contentPane.setLayout(null); contentPane.setBackground(Color.DARK_GRAY); JButton btnNewButton = new JButton("Solve"); btnNewButton.setBounds(10, 285, 89, 23); btnNewButton.setBackground(Color.white); contentPane.add(btnNewButton); btnNewButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { readSudoku(); } }); for(int i=0; i<9; i++){ for(int j=0; j<9; j++){ allField[i][j] = new JTextField(); allField[i][j].setBounds(10 + i * 30, 10 + j * 30, 30, 30); allField[i][j].setColumns(1); allField[i][j].setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY, 1)); contentPane.add(allField[i][j]); } } for(int i=3; i<6; i++){ for(int j=0; j<3; j++){ allField[i][j].setBackground(Color.LIGHT_GRAY); } } for(int i=3; i<6; i++){ for(int j=6; j<9; j++){ allField[i][j].setBackground(Color.LIGHT_GRAY); } } for(int i=0; i<3; i++){ for(int j=3; j<6; j++){ allField[i][j].setBackground(Color.LIGHT_GRAY); } } for(int i=6; i<9; i++){ for(int j=3; j<6; j++){ allField[i][j].setBackground(Color.LIGHT_GRAY); } } } public void readSudoku(){ int [][]array = new int[9][9]; //first [] is the row second [] the column. Order differs from declaration of allField[][] but is important to know for Main.java. for( int i=0; i<9; i++){ for( int j=0; j<9; j++){ if(!allField[i][j].getText().isEmpty()) array[i][j] = Integer.parseInt(allField[i][j].getText()); else array[i][j] = 0; } } Main start = new Main(); start.startSolving(array); } public void writeSudoku(int[][] array){ for(int i=0; i<9; i++){ for(int j=0; j<9; j++){ System.out.println(String.valueOf(array[i][j])); allField[i][j].setText(String.valueOf(array[i][j])); } } } }
Die Main.java ist irrelevant, da dort alles super verläuft.
Ganz unten in der GUI.java "System.out.println(String.valueOf(array[i][j]));" habe ich eingefügt um zu kontrollieren ob das entgegengenommene Array die Zahlen enthält. Tut es! Es muss daran liegen, dass ich die writeArray()-Methode aus einer anderen Klasse aufrufe und Java mit dem allField[i][j] nicht zurechtkommt.
Anmerkung:
Ich hatte vorher bereits (umständlich) in der GUI-main-methode ein Objekt deklariert, des Typs Main welches eine Funktion in der Main.java aufruft, die ein Objekt des Typs GUI deklariert, aufruft und ausliest...
Ich wollte alle grundlegenden Befehle in der Main.java haben. Daher diese Verzweigung. Da ich dabei wieder von Main nach GUI verwiesen habe hatte ich ein ähnliches Problem. Dabei wollte ich allField[i][j] auslesen und er gab mir nichts aus. Dies habe ich gelöst indem ich die readSudoku()-Methode direkt aus der GUI.java aufrufe.
Ich wollte alle grundlegenden Befehle in der Main.java haben. Daher diese Verzweigung. Da ich dabei wieder von Main nach GUI verwiesen habe hatte ich ein ähnliches Problem. Dabei wollte ich allField[i][j] auslesen und er gab mir nichts aus. Dies habe ich gelöst indem ich die readSudoku()-Methode direkt aus der GUI.java aufrufe.
Ich verstehe aber nicht warum dies so ist und auch nicht wie ich das umgehen kann.
Main.java (wen es interessiert):
Code:
public class Main{ public void startSolving(int[][] array){ int workArray[][] = array; //contains the Sudoku int counter = 1; //counts how many nums have been solved in one round. 1 to get into while. long startingTime = System.nanoTime(); //Time that solving start. Need for time measurement. while(counter>0){ counter = 0; //set to 0. now the counting begins. for(int n=1; n<10; n++){ //for every number int tempArray[][] = new int[9][9]; //contains the possibilities of the choosen number. If it can be at [x][y] for(int r=0; r<9; r++){ //for every row for(int c=0; c<9; c++){ //for every column if(workArray[r][c] == 0){ //if number already exists at this field nothing is left to show (*) if(!checkRow(r, n, c, workArray) && !checkColumn(c, n, r, workArray) && !checkBox(r, c, n, workArray)) tempArray[r][c] = 1; //if num is nowhere set 1(possible) else tempArray[r][c] = 0; //is num is anywhere set 0(not p) } else tempArray[r][c] = 0; //(*)even though tempArray still needs to be written } } //now it need to be checked if there is just one p in every row/column/box //doing that by looking for a field with p of num being there and looking if there are other p in this special row/column/box for(int r=0; r<9; r++){ //for every row for(int c=0; c<9; c++){ //for every column if(tempArray[r][c] == 1){ //if it is possible for the number to be there -> check if it is must be there if(checkRowPossibilities(r, c, tempArray)){ workArray[r][c] = n; counter++;}//check the row else if(checkColumnPossibilities(c, r, tempArray)){ workArray[r][c] =n; counter++;} //check the column else if(checkBoxPossibilities(r, c, tempArray)){ workArray[r][c] = n; counter++;} //check the box } } } } } long estimatedTime = System.nanoTime() - startingTime; //Time that was needed. GUI endSudoku = new GUI(); endSudoku.writeSudoku(workArray); System.out.println(estimatedTime); } // takes integer row that represents the row. // takes integer num that represents the searched number. // takes integer field that represents the column/field that is tested in main method. // takes array that represents the Sudoku. // returns if number is already in this row. public static boolean checkRow(int row, int num, int field, int[][] array){ for( int c=0; c<9; c++){ if(c != field) if(array[row][c] == num) return true; } return false; } // takes integer column that represents the column. // takes integer num that represents the searched number. // takes integer field that represents the row/field that is tested in main method. // takes array that represents the Sudoku. // returns if number is in this column. public static boolean checkColumn(int column, int num, int field, int[][] array){ for( int r=0; r<9; r++){ if(r != field) if(array[r][column] == num) return true; } return false; } // takes integer row that represents the row. // takes integer column that represents the column. // takes integer num that represents the searched number. // takes array that represents the Sudoku. // returns if number is in this box. public static boolean checkBox(int row, int column, int num, int[][] array){ if(row == 0 || row == 1 || row == 2){ //row is one of the first 3 return checkBoxColumn( column, row, num, 0, array); } else if(row == 3 || row == 4 || row == 5){ //row is one of the middle 3 return checkBoxColumn( column, row, num, 3, array); } else{ //row is one of the last 3 return checkBoxColumn( column, row, num, 6, array); } } // extention of checkBox. // takes integer column that represents the column. // takes integer row that represents the row. // takes integer num that represents the searched number. // takes array that represents the Sudoku. // takes integer startRow that represents the starting number for the for-loop. Comes from the row-check. // returns if number is in the box.(to checkBox) public static boolean checkBoxColumn(int column, int row, int num, int startRow, int[][] array){ if(column == 0 || column == 1 || column == 2){ //column is one of the first 3 for(int r=startRow; r<startRow+3; r++){ for(int c=0; c<3; c++){ if(r != row || c != column) if(array[r][c] == num) return true; } } } else if(column == 3 || column == 4 || column == 5){ //column is one of the middle 3 for(int r=startRow; r<startRow+3; r++){ for(int c=3; c<6; c++){ if(r != row || c != column) if(array[r][c] == num) return true; } } } else{ //column is one of the last 3 for(int r=startRow; r<startRow+3; r++){ for(int c=6; c<9; c++){ if(r != row || c != column) if(array[r][c] == num) return true; } } } return false; } // takes integer row that represents the row. // takes integer field that represents the column/field that is tested in main method. // takes array that represents the posibilities of num being at [x][y]. // returns if it is the only possibility in this row. public static boolean checkRowPossibilities(int row, int field, int[][] array){ for( int c=0; c<9; c++){ if(c != field) if(array[row][c] == 1) return false; //returns false if the checked field is not alone in this row } return true; //returns true -> yes IS alone! } // takes integer column that represents the column. // takes integer field that represents the row/field that is tested in main method. // takes array that represents the possibilities of num being at [x][y]. // returns if it is the only possobility in this column. public static boolean checkColumnPossibilities(int column, int field, int[][] array){ for( int r=0; r<9; r++){ if(r != field) if(array[r][column] == 1) return false; //returns false if the checked field is not alone in this row } return true; //returns true -> yes IS alone! } // takes integer row that represents the row. // takes integer column that represents the column. // takes array that represents the possibilities of num being at [x][y]. // returns if it is the only possobility in this column. public static boolean checkBoxPossibilities(int row, int column, int[][] array){ if(row == 0 || row == 1 || row == 2){ //row is one of the first 3 return checkBoxPossibilitiesColumn( column, row, 0, array); } else if(row == 3 || row == 4 || row == 5){ //row is one of the middle 3 return checkBoxPossibilitiesColumn( column, row, 3, array); } else{ //row is one of the last 3 return checkBoxPossibilitiesColumn( column, row, 6, array); } } // extention of checkBoxPossibilities. // takes integer column that represents the column. // takes integer row that represents the row. // takes array that represents the possibilities of num being at [x][y]. // takes integer startRow that represents the starting number for the for-loop. Comes from the row-check. // returns if it is the only possobility in this column.(to checkBox) public static boolean checkBoxPossibilitiesColumn(int column, int row, int startRow, int[][] array){ if(column == 0 || column == 1 || column == 2){ //column is one of the first 3 for(int r=startRow; r<startRow+3; r++){ for(int c=0; c<3; c++){ if(r != row || c != column) if(array[r][c] == 1) return false; //returns false if the checked field is not alone in this row } } } else if(column == 3 || column == 4 || column == 5){ //column is one of the middle 3 for(int r=startRow; r<startRow+3; r++){ for(int c=3; c<6; c++){ if(r != row || c != column) if(array[r][c] == 1) return false; //returns false if the checked field is not alone in this row } } } else{ //column is one of the last 3 for(int r=startRow; r<startRow+3; r++){ for(int c=6; c<9; c++){ if(r != row || c != column) if(array[r][c] == 1) return false; //returns false if the checked field is not alone in this row } } } return true; //returns true -> yes IS alone! } }