Sudoku Programmers Forum Index

 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister   ProfileProfile   Log inLog in          Games  Calendar

Log in to check your private messagesLog in to check your private messages   

need some starting help for Java Sudoku
Goto page Previous  1, 2, 3, 4, 5
 
Post new topic   Reply to topic    Sudoku Programmers Forum Index -> Programming sudoku
View previous topic :: View next topic  
Author Message
VIDEN

Joined: 02 Oct 2006
Posts: 55
:
Location: Germany

Items
PostPosted: Thu Oct 26, 2006 8:20 am    Post subject: Reply with quote

After I worked through all sorts of swing-tutorials I looked at the NetBeans GUI Editor tutorials and after that I went throgh a few JTable tutorials.

Well, JTable really seemes to be one of the most complicated swing classes and it took me quite a while to just understand a bit of it.

Now I came to the conclusion that I need the following things:

A custom TableModel
and a custom TableCellEditor

Well these to components really are very complicated and I don't quite understand everything.
The TableCellEditor is only used while the User is editing the cells and verifys the users inputs.

The TableModel Tells the JTable what to write in the cells and can add and delete rows and columns and so on.

Well after I call solve for example and I want to write the values of my new userMatrix into the JTable, how do I do that?
just call TableModel again or will this be done automaticly?

I wrote a custom TableModel class based on an example I found, and it actually works!

Code:
class MyTableModel extends AbstractTableModel {
        private boolean DEBUG = true;
        private String[] columnNames = {"c0",
                                        "c1",
                                        "c2"};
        private Cell [][] data = new Cell[3][3];
        int i=0;
       
        public MyTableModel(int boxNum){
            for(int r=0;r<3;r++){
                for(int c=0;c<3;c++){
                    data[r][c]=currentBoard.userMatrix.boxes[boxNum].cells[i++];
                }
            }
        }

        public int getColumnCount() {
            return 3;
        }

        public int getRowCount() {
            return 3;
        }

        public String getColumnName(int col) {
            return columnNames[col];
        }

        public Object getValueAt(int row, int col) {
            if(data[row][col].getValue()==0)
                return null;
            return new Integer (data[row][col].getValue());
        }

        /*
         * JTable uses this method to determine the default renderer/
         * editor for each cell.  If we didn't implement this method,
         * then the last column would contain text ("true"/"false"),
         * rather than a check box.
         */
        public Class getColumnClass(int c) {
            return Integer.class;
        }

        /*
         * Don't need to implement this method unless your table's
         * editable.
         */
        public boolean isCellEditable(int row, int col) {
            //Note that the data/cell address is constant,
            //no matter where the cell appears onscreen.
            if (data[row][col].isOriginal())
                    return false;
            return true;
        }

        /*
         * Don't need to implement this method unless your table's
         * data can change.
         */
        public void setValueAt(Object value, int row, int col) {
            if (DEBUG) {
                System.out.println("Setting value at " + row + "," + col
                                   + " to " + value
                                   + " (an instance of "
                                   + value.getClass() + ")");
            }

            data[row][col].num =(Integer) value;
            fireTableCellUpdated(row, col);

            if (DEBUG) {
                System.out.println("New value of data:");
                printDebugData();
            }
        }

        private void printDebugData() {
            int numRows = getRowCount();
            int numCols = getColumnCount();

            for (int i=0; i < numRows; i++) {
                System.out.print("    row " + i + ":");
                for (int j=0; j < numCols; j++) {
                    System.out.print("  " + data[i][j]);
                }
                System.out.println();
            }
            System.out.println("--------------------------");
        }
    }   
}


But I would like the Original Cell Numbers to be colored blue, but I didn't find a way to manage that Sad

oh and I found this:
http://java.sun.com/docs/books/tutorial/uiswing/components/examples/IntegerEditor.java
It looks like i could just use it like it is to edit my cells.

Greets David
Back to top
View user's profile Send private message
VIDEN

Joined: 02 Oct 2006
Posts: 55
:
Location: Germany

Items
PostPosted: Fri Oct 27, 2006 8:20 am    Post subject: Reply with quote

Hmm okay I desided to just use one JTable because using 9 makes everything more complicated and the code gets confusing and too large.

So far erverything works. The solve Butten works. Solving given and custom Sudokus.
New works fine too.

But in the moment every Cell is looks the same, and they don't get colored so I'll have to work out a custom TableCellRenderer.

But I still have a little Problem, ererything wokrs fine but I didn't Implement it the way it should be.
These are my action events. After doing the the changes using controller the grid has to be painted new, I call updateTables() but the way I update there isn't really nice. There propybly is a better way but I couldn't find one.

Code:
private void solveActionPerformed(java.awt.event.ActionEvent evt) {                                     
        saveTablesToBoard();
        Integer val=(Integer) numToSolve.getValue();
        controller.solve(currentBoard, val.intValue());
        updateTables();
    }                                     
   
    private void checkActionPerformed(java.awt.event.ActionEvent evt) {                                     
        saveTablesToBoard();
        controller.check(currentBoard);
        updateTables();
    }                                     
   
    private void loadNewActionPerformed(java.awt.event.ActionEvent evt) {                                       
        int difficulty=selectDifficulty.getSelectedIndex();
        currentBoard= new Board();
        if(selectDifficulty.getSelectedIndex()<3)
            currentBoard=controller.getNewPuzzle(difficulty);
        updateTables();
    }                                       
   
    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new SwingGUI().setVisible(true);
            }
        });
    }
   
    private void updateTables(){
        if(DEBUG)
            currentBoard.userMatrix.print();
        gridTableModel= new SwingGUI.MyTableModel();
        grid.setModel(gridTableModel);
    }
Back to top
View user's profile Send private message
Jean-Christophe

Joined: 19 Mar 2006
Posts: 126
:
Location: Belgium

Items
PostPosted: Fri Oct 27, 2006 4:00 pm    Post subject: Reply with quote

If your make your Board extends from AbstractTableModel and create your JTable view using your Board as TableModel, then it will be simpler IMO.

You can update your view whenever a cell changes with fireTableCellUpdated() or the whole board with fireTableDataChanged(). This would replace your updateTables().

And the other way. You may implement isCellEditable() in your Board to return false for given clues and true for the others. Whenver the user inputs some value in the cell of the JTable, your Board.setValueAt() will be called for editable cells.

If you want to validate the user input, look at InputVerifier.
_________________
Jean-Christophe
"When you have eliminated the impossible, whatever remains, however improbable, must be the truth." Sherlock Holmes.
Back to top
View user's profile Send private message Visit poster's website
VIDEN

Joined: 02 Oct 2006
Posts: 55
:
Location: Germany

Items
PostPosted: Fri Oct 27, 2006 4:35 pm    Post subject: Reply with quote

In the meantime I have come much further.

I am using a 9x9 JTable that is colored by an custem CellRenderer, it looks really nice ^^

I already have isCellEditable() implemented, the original cells and solved cells are not editable anymore Board.setValueAt() is than called.
I am using a IntegerCellEditor from SUN, but I'm not quite satisfied with it yes. I'll have to work out a few more things there.

I now have one week off but I think I might keep doing a few thing on the Program Wink
I have a few questions I'll ask you when I keep working on it.

Heres the source
http://viden.vi.funpic.de/Sudoku/Sudkou_VIDEN_v0.32.zip

Greets David
Back to top
View user's profile Send private message
VIDEN

Joined: 02 Oct 2006
Posts: 55
:
Location: Germany

Items
PostPosted: Sun Oct 29, 2006 9:42 pm    Post subject: Reply with quote

Hey, I need a bit of your help again. I extended my solver so that it counts the possible number of solutions.
But I couldn't test this funktion fully because I had no puzzles to test where I new the exact number of solutions. So do you maby have a few puzzles with like 2-10 solutions so I can see if it works right?

There only was one woth 2 possible solutions on the Page you gave me that Ruud made. but I'd like to have a few more

Thx David
Back to top
View user's profile Send private message
VIDEN

Joined: 02 Oct 2006
Posts: 55
:
Location: Germany

Items
PostPosted: Mon Nov 13, 2006 7:50 am    Post subject: Reply with quote

Okay, I'm back.
It took me a bit longer cause I had to go to University last week.

I'll do my documentation first and than try to get rid of a few Bugs.

Greets David
Back to top
View user's profile Send private message
Pat

Joined: 06 Sep 2006
Posts: 128
:

Items
PostPosted: Mon Nov 13, 2006 12:00 pm    Post subject: re: multiple answers Reply with quote

VIDEN wrote:
I extended my solver so that it counts the possible number of solutions.

But I couldn't test this function fully because I had no puzzles to test where I knew the exact number of solutions.

So do you maybe have a few puzzles with like 2-10 solutions so I can see if it works right?

There only was one woth 2 possible solutions on the Page you gave me that Ruud made.
but I'd like to have a few more



5 answers:

JPF
Code:
 . 1 . | . . 6 | . . .
 . 5 7 | . 9 . | 2 . .
 6 . . | . . 8 | 4 . 5
-------+-------+-------
 . 7 . | 4 8 . | . . .
 . . . | . . . | . . .
 . . . | . . . | 7 . 4
-------+-------+-------
 2 4 5 | . . . | . 9 .
 . . 9 | . 6 . | . . .
 . . . | . 3 . | . 8 .


JPF
Code:
 . . . | 2 . 8 | 1 . .
 . 4 3 | . . . | . 8 .
 . 9 . | . . . | . 5 .
-------+-------+-------
 1 . . | . . 6 | 7 . .
 . . . | 5 . . | 2 6 .
 6 . . | . 2 . | . . .
-------+-------+-------
 . 7 . | . . . | . . .
 . . . | . 6 . | 9 . .
 . . 8 | 9 . 5 | . . 1


maria45
Code:
 5 . . | 7 . . | . 1 .
 . 6 . | . 4 . | . . 7
 . . 3 | . . 2 | . . .
-------+-------+------
 . . 4 | 8 . . | 2 . .
 . 1 . | . 3 . | . 8 .
 2 . . | . . 9 | . . 4
-------+-------+------
 . . 8 | 6 . . | 3 . .
 . 3 . | . 2 . | . 5 .
 9 . . | . . 5 | . . 6


JPF
Code:
 9 . . | 1 . . | . 7 .
 . . 6 | . 4 . | . 8 3
 . . . | . . . | . . .
-------+-------+-------
 . 7 . | 5 . . | . . .
 . . . | . . 3 | . . .
 . . . | 9 . . | . 5 4
-------+-------+-------
 . 1 5 | . . 2 | 3 4 .
 . . 3 | 7 5 . | 2 . .
 . 8 . | 6 . . | . . .
Back to top
View user's profile Send private message Visit poster's website
VIDEN

Joined: 02 Oct 2006
Posts: 55
:
Location: Germany

Items
PostPosted: Tue Nov 14, 2006 2:58 pm    Post subject: Reply with quote

Thx @ Pat now it counts them out right... went back to the way Jean-Christophe did it in my 0.05 version.

Well I after optimizing and debugging the Programm a bit, I came to the conclusion that I will have to implement changing Digits in my Observe Pattern so that I can make my Board extend the AbstractTableModel as you suggested.

This far, if I set the value of a Cell, all buddies get informed and the cellValue is erased form their Candidate list.
But this only works if the old value was a "0".

If it was something else, the old number has to be restored in the Candidates list, as far as there is no other Cell with the same number.
So practically every Cell will have to check if one of its Buddys has the oldValue as Digit. If yes, everything stays the same, if no the OldValue has to be restored in the Candidate list.
Oh and Cells that already have a Number arne't allowed to add Candidates.

This seemes to be really complicated, do you understand what I mean?
And do you have an idea of how to implement this?

Greets David

Code that will have to be changed:

Method in CELL:
Code:

    public void setValue(int value) {
        int oldValue=num;
        num=value;
        if(value>0) {
            candidates.emptySet();
            candidates.addBit(value);
        }
        setChanged();
        notifyObservers(num);
    }


Observers Method in HOUSE:
Code:
    /**Removes the Number of the Observed Object from the other Cells Canidates */
    public void update( Observable o, Object obj ){
        Cell cell = (Cell)o;
        int v = cell.getValue();
        for(int i=0;i<9;i++){
            if(cells[i].getRow()==cell.getRow() && cells[i].getColumn()==cell.getColumn())
                continue;
            cells[i].removeCandidate(v);
        }
    }
Back to top
View user's profile Send private message
Jean-Christophe

Joined: 19 Mar 2006
Posts: 126
:
Location: Belgium

Items
PostPosted: Tue Nov 21, 2006 11:02 am    Post subject: Reply with quote

I think I understand your problem.
You can do it the way you said.
Maybe it will be easier to implement undo/redo features.
_________________
Jean-Christophe
"When you have eliminated the impossible, whatever remains, however improbable, must be the truth." Sherlock Holmes.
Back to top
View user's profile Send private message Visit poster's website
VIDEN

Joined: 02 Oct 2006
Posts: 55
:
Location: Germany

Items
PostPosted: Tue Nov 21, 2006 2:43 pm    Post subject: Reply with quote

Well I found a way to do it and it works, but it just doesn't look so good in my eyes. Propably not the way a good Programmer would do it:

Method in Cell:

Code:
public void setValue(int value) {
        oldNum=num; //int variable Cell.oldNum this is whats bothering me to have to add an extra Variable to Cell
        num=value;
        if(value>0) {
            candidates.emptySet();
            candidates.addBit(value);
        }
        if(oldNum!=value){
            setChanged();
            notifyObservers(num);
        }
    }


Method in House

Code:
public void update( Observable o, Object obj ){
        Cell cell = (Cell)o;
        int v = cell.getValue();
        for(int i=0;i<9;i++){
            if(cells[i].getRow()==cell.getRow() && cells[i].getColumn()==cell.getColumn())
                continue;
            cells[i].removeCandidate(v);
        }
        if(cell.getOldNum()!=0){
            for(int i=0;i<9;i++){
                if(cells[i].getRow()==cell.getRow() && cells[i].getColumn()==cell.getColumn())
                    continue;
                cells[i].checkCandidate(cell.getOldNum());
            }
        }
    }


If the oldNum wasnt 0 alle buddies now have to check if this oldNum could be a Candidate for them using the Cell.checkCandidate() Method

Method in Cell
Code:
public void checkCandidate(int candidate){
        candidates.addBit(candidate);
        HashSet buddies=getBuddies();
        Iterator buddiesIter = buddies.iterator();
        while(buddiesIter.hasNext()){
            Cell c=(Cell)buddiesIter.next();
            if(c.getValue()==candidate){
                removeCandidate(candidate);
                return;
            }
        }
    }


As I sayed it works fine but isn't really good programming...

I have also made Board to my TableModel now and I verify the user-Input with a KeyEventListener.
I thought about the Generator, but if I want one with different difficulties I will have to implement different solving techniques like naked Singles, hidden Singles ect.
I started off with the naked and hidden Single which are quite easy but since I will have to go to University from December to March I wan't to have a stable, working release till then. So I descidet to use a Sudoku DataBase for now.

I want to use 3 *.txt-Files:
EasyPuzzles.txt / MediumPuzzles.txt / HardPuzzles.txt

The Puzzles are saved in lines like:
000306500800500000010000040900080020000000000040060001050000010000009002006108000
I read them out with
Code:
try {
            BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream("EasyPuzzles.txt")));
            String line;
            while( null != (line = in.readLine()) ) {
                Board board= new Board(StringToIntArr(line));
                this.addBoard(board, 0);
            }
            in.close();
        } catch( Exception ex ) {
            System.out.println( ex );
        }


The only thing missing now are the Puzzles ^^
I'll have to see where to get them from...

Greets David
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Sudoku Programmers Forum Index -> Programming sudoku All times are GMT
Goto page Previous  1, 2, 3, 4, 5
Page 5 of 5

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
Sudoku Programmers topic RSS feed 


Powered by phpBB © 2001, 2005 phpBB Group

Igloo Theme Version 1.0 :: Created By: Andrew Charron