Java Forum / First Aid / December 2005
Calling a Subroutine
Mike - 11 Dec 2005 00:51 GMT I'm fumbling again. I'm trying to write this Sudoku solver to work up my java skills. What I thought to do was to create a fairly static subroutine to set up the board with values until I have time to master the gui interface. So I thought I should write a separate class SudokuSetUp to contains this code, then later I can write the GUI code in there. I didn't want to write this in my main class the SudokuGame.
But now I can't figure out how to pass the entire array that is the board over to the other class to insert values into some of the cells.
I tried
sudokuBoard = SudokuSetup(sudokuBoard);
but that complained that it could not find the method SudokuSetup in my SudokuGame class.
Then I tried
sudokuBoard = SudokuSetup.setvalues(sudokuboard)
but that complained that non-static method setValues(SudokuCell[][]) cannot be referenced from a static context
I''m posting my code here, apologies if it is too much code.
Class SudokuGame:
import java.text.*; import java.util.*;
public class SudokuGame { public static void main (String[] args) {
SudokuCell[] [] arrSudokuBoard = new SudokuCell[9] [9];
// set up a board with all cells initialized. for (int i=0; i<9; i++) { for (int j=0; j<9; j++) { arrSudokuBoard[i] [j] = new SudokuCell( i, j); } }
// set certain cells to specific values arrSudokuBoard = SudokuSetUp.setValues(arrSudokuBoard);
// print current board for (int i=0; i<9; i++) { System.out.println("x-value " + i); for (int j=0; j<9; j++) { System.out.print(arrSudokuBoard[i] [j].toString()); }
System.out.println(); }
} }
Class SudokuCell: import java.util.*; import java.text.*;
public class SudokuCell { // Declare instance variables private int xCoord; private int yCoord; private int xRegionCoord; private int yRegionCoord; List<Integer> cell = new ArrayList<Integer>();
// Constructor with x,y reference public SudokuCell(int x, int y) { xCoord = x; yCoord = y; xRegionCoord = xCoord/3; yRegionCoord = yCoord/3; for (int i=1; i<10; i++) { cell.add(i); }
}
public void setValue(int value) { cell.retainAll(Collections.singleton(value)); }
public void removeValue(int value) { cell.remove(value); }
public int[] getRegion() { int[] regionCoord = new int[2]; regionCoord[0] = xRegionCoord; regionCoord[1] = yRegionCoord; return regionCoord; }
public int [] [] getXAdj() { int [] [] xAdj = new int [2] [2]; int pos = xCoord % 3; switch (pos) { case 0: xAdj[1] [1] = xCoord + 1; xAdj[1] [2] = yCoord; xAdj[2] [1] = xCoord + 2; xAdj[2] [2] = yCoord; break; case 1: xAdj[1] [1] = xCoord - 1; xAdj[1] [2] = yCoord; xAdj[2] [1] = xCoord + 1; xAdj[2] [2] = yCoord;
break; case 2: xAdj[1] [1] = xCoord - 2; xAdj[1] [2] = yCoord; xAdj[2] [1] = xCoord - 1; xAdj[2] [2] = yCoord; break; } return xAdj; }
public int [] [] getYAdj() { int [] [] yAdj = new int [2] [2]; int pos = yCoord % 3; switch (pos) { case 0: yAdj[1] [1] = xCoord; yAdj[1] [2] = yCoord + 1; yAdj[2] [1] = xCoord; yAdj[2] [2] = yCoord + 2; break; case 1: yAdj[1] [1] = xCoord; yAdj[1] [2] = yCoord - 1; yAdj[2] [1] = xCoord; yAdj[2] [2] = yCoord + 1;
break; case 2: yAdj[1] [1] = xCoord; yAdj[1] [2] = yCoord - 2; yAdj[2] [1] = xCoord; yAdj[2] [2] = yCoord - 1; break; } return yAdj; }
public String toString() { String outString = new String("Cell at X("+xCoord+"),Y("+yCoord+"):("+cell+")"); return outString; } }
Class SudokuSetup:
import java.text.*; import java.util.*;
public class SudokuSetUp { public class SudokuSetup { }
public SudokuCell[] [] setValues(SudokuCell board [] []) { board[0] [0].setValue(1); board[2] [0].setValue(9); board[3] [0].setValue(3); board[7] [0].setValue(2); board[0] [1].setValue(7); board[2] [1].setValue(3); board[3] [1].setValue(6); board[4] [1].setValue(2); board[5] [1].setValue(5); board[6] [1].setValue(1); board[1] [2].setValue(2); board[3] [2].setValue(1); board[8] [2].setValue(7); board[1] [3].setValue(6); board[3] [3].setValue(8); board[5] [3].setValue(1); board[1] [4].setValue(5); board[2] [4].setValue(2); board[6] [4].setValue(8); board[7] [4].setValue(7); board[3] [5].setValue(2); board[5] [5].setValue(3); board[7] [5].setValue(5); board[0] [6].setValue(4); board[5] [6].setValue(2); board[7] [6].setValue(3); board[2] [7].setValue(6); board[3] [7].setValue(7); board[4] [7].setValue(3); board[5] [7].setValue(8); board[6] [7].setValue(4); board[8] [7].setValue(2); board[1] [8].setValue(3); board[5] [8].setValue(9); board[6] [8].setValue(7); board[8] [8].setValue(5);
return board; } }
Thanks Mike
IchBin - 11 Dec 2005 01:48 GMT [snip code]
> public class SudokuGame > { > public static void main (String[] args) > { SudokuSetup sudokuSetUp = new SudokuSetup();
[snip code]>
> // set certain cells to specific values > arrSudokuBoard = SudokuSetUp.setValues(arrSudokuBoard); arrSudokuBoard = sudokuSetUp.setValues(arrSudokuBoard);
[snip code]
I just added the one line above and changed one line to new reference.
 Signature
Thanks in Advance... IchBin, Pocono Lake, Pa, USA http://weconsultants.servebeer.com/JHackerAppManager __________________________________________________________________________
'If there is one, Knowledge is the "Fountain of Youth"' -William E. Taylor, Regular Guy (1952-)
Mike - 11 Dec 2005 02:08 GMT Mike - 11 Dec 2005 16:55 GMT > [snip code] > > [quoted text clipped - 14 lines] > > I just added the one line above and changed one line to new reference. Based on what you showed me, I went back to my textbook and re-read the bits about static methods and variables. Basically, what I understand is that a non-static method must be instantiated (as you did) before it can be used. Alternatively, I can make the method static and then I don't have to instantiate it.
My textbook doesn't dwell much on this and suggests that it will become clearer when I use it. But I'm confused. On the surface it _seems_ easier to simply make the method static and then I dont have to instantiate it. What is the downside? In my main class I'm creating several methods, and I found the same issue that I have to either instantiate the methods or make them static. What is the best way to proceed?
Thanks Mike
IchBin - 11 Dec 2005 17:56 GMT >> [snip code] >>> public class SudokuGame [quoted text clipped - 29 lines] > Thanks > Mike It is better to use static methods only when really needed. This so that you can really take advantage of Java and build OOP\OOD applications.
This has been answered in other emails. Look at this thread.. http://groups.google.com/group/comp.lang.java.programmer/browse_thread/thread/7a 25ef704fd23c12/ba18da7e9a1e73f0?lnk=st&q=%22Styles+of+programming%22&rnum=2#ba18 da7e9a1e73f0 or do a google against groups with "Styles of programming"
At your leisure look at 'The Java Language Specification, Third Edition' http://java.sun.com/docs/books/jls/third_edition/html/j3TOC.html
'Thinking in Java, 3rd ed. Revision 4.0' http://jamesthornton.com/eckel/TIJ-3rd-edition4.0/TIJ3.htm
 Signature Thanks in Advance... IchBin, Pocono Lake, Pa, USA http://weconsultants.servebeer.com/JHackerAppManager __________________________________________________________________________
'If there is one, Knowledge is the "Fountain of Youth"' -William E. Taylor, Regular Guy (1952-)
Rhino - 11 Dec 2005 17:57 GMT >> [snip code] >> > [quoted text clipped - 28 lines] > instantiate the methods or make them static. What is the best way to > proceed? Have a look at the "Styles of Programming" thread on comp.lang.java.programmer which was created today, particularly the remarks by Francesco Devittori: I think he states the basic principle very well.
My remarks in the "non-static context" thread on comp.lang.java.help (started on Dec 9) _may_ also be useful to you.
Rhino
Mark Haase - 11 Dec 2005 18:14 GMT > Based on what you showed me, I went back to my textbook and re-read the > bits about static methods and variables. Basically, what I understand [quoted text clipped - 9 lines] > instantiate the methods or make them static. What is the best way to > proceed? Not quite...you can't "instantiate a method". But a non-static method can only be called on a particular instance of that class, and you do have to instantiate an object before you call a non-static method on it. In memory, though, there's only one copy of the method.
A static method, as you've noted, can be called without having any objects lying around.
What's the practical difference? Use non-static methods for most things. In a non-static context, you have a reference to "this" (whatever object the method was called on). In general, good OO design is going to involve calling non-static methods on objects rather than calling static methods on classes. This is true because notice what happens when you use static methods to do everything: you're basically writing procedural code.
Static methods do have uses (obviously). The main method is always static, for instance. If it wasn't, what object would it be called on? It gets called before you've instantiated any objects, so it must be static. (In other languages, they get around this problem by instantiating a root object for you and then calling the "main" method on it.)
Static methods also make sense for algorithms which don't work on objects or may not often be used in an OO context. A lot of the java.lang.Math classes use static methods, because you wouldn't want to call, say sqrt() or sin() or cos() on most objects. You'd rather just call them statically and pass a few primitives as arguments. There are lots of static methods in java.lang.String as well for the same reason: convenience.
Finally, static methods are useful whenever you're trying to control access to a class. If you didn't want a class to be instantiable, for instance, you could mark all of its constructors as private and then provide static methods to instantiate and return new objects. Such a method is called a "factory method" because it does the work of building a new object for you. Why would you want to do this? I can name one reason: if you're writing a class that represents a constrained computing or i/o resource. So if you write a class that represents serial ports, for instance, most computers only have one or two. So you could write your class, mark the contructors as private (so nobody else can instantiate a serial port except the serial port class itself), and then provide static methods which instantiate serial port objects and make sure that no more than one piece of code ever has a reference to the same serial port.
Hope this helps, search on google for "java math" and "java string" and read through the APIs that pop up. It should give you a better feel what static is for.
|\/| /| |2 |< mehaase(at)gmail(dot)com
Mike - 11 Dec 2005 19:56 GMT That was great. Thanks to IchBin, Rhino and Mark Haase. I now have a clearer understanding of the static issue.
Now however, I'm in doubt as to my design for my Sudoku solver. I'll try to outline my thinking, hopefully it is not too unclear and someone can tell me if I'm on the right track or if a better design is possible in Java.
I have a main class SudokuGame
In this class, the main method creates a sudokuBoard, a 9X9 array of SudokuCells The main method then calls (invokes?) SudokuSetUp to get the configuration of the current game board. For now I've got only one game configuration, I'll make SudokuSetUp the piece (module?) that interacts with the user to get the configuration once I've got the rest of this in place.
The main method then iterates over a number of other methods for solving various possible configurations. It does this for as long as each iteration results in more solved cells than in the previous iteration.
The methods in SudokuGame that main can invoke are routines such as a) count the number of solved cells (a solved cell has only one value). b) remove a value from a region, a row or a column. c) identify a region with only two cells with the same value in both and where the cells are in line either horizontally or vertically. d) identify a row, column or region where there is only one cell that has a particular value.
The class SudokuCell creates an instance (one of 81) of the cells in the array. Each cell has a List with, initially, 9 values. Each cell has methods to return the region the cell belongs to, the (x,y) co-ordinates of the other 8 cells in the same region, the (x,y) coordinates of the other cells in the same region in the same row/column, as well as methods to set the value of the cell to a single value or to remove a specific value from the cell list.
I considered making this a class that extends ArrayList, but I was not sure about that. I think I may rewrite it to extend ArrayList so that I don't have to create a method in my class for every method I want to use on the ArrayList in SudokuCell. Advice on this will be greatly appreciated.
So currently I have 3 classes. SudokuGame (main + manipulation for the sudokuBoard), SudokuSetUp (create initial board configuration) and SudokuCell(manipulate the cell contents and provide navigation info on the cell position on the board/column, row and region).
I don't see a problem with making SudokuSetUp static, it can only be invoked once from SudokuGame and it serves no purpose to have this class instantiated.
Clearly the SudokuCell class is instantiated for each cell in the sudokuBoard, each cell an instance of the class.
I think I can make the methods in SudokuGame also static, they don't need to be instantiated at this time, perhaps if I invent a solution method that is recursive?
I'm also toying with making the entire sudokuBoard a static variable so that I don't have to keep passing and returning it to the various methods in the SudokuGame class that I want to operate on the board.
Again, I hope this is clear and I appreciate any feedback on the design I've got (I don't mind changing it, after all I'm only doing it to learn).
Thanks Mike
Mark Haase - 11 Dec 2005 23:38 GMT > In this class, the main method creates a sudokuBoard, a 9X9 array of > SudokuCells [quoted text clipped - 3 lines] > with the user to get the configuration once I've got the rest of this > in place. Why not make SudukoBoard its own class? It isn't strictly necessary, but if you're going to be providing a graphical interface, then it makes more sense to have a SudukoBoard class which can draw itself.
Is SudokuSetUp a method or a class? Are you referring to setting up which squares initially have numbers in them? setUp should probably be a static method -- unless you want to have different ways of setting up the board (download from internet, manual input, random puzzle, etc).
> The class SudokuCell creates an instance (one of 81) of the cells in > the array. Each cell has a List with, initially, 9 values. Each cell [quoted text clipped - 9 lines] > use on the ArrayList in SudokuCell. Advice on this will be greatly > appreciated. The SudokuCell class sounds good as it is. Why does it return the x,y coords of other cells in its region? It shouldn't have to. In fact, it doesn't even necessarily have to know its region -- although that is a convenient (and acceptable) shortcut if you're not going to write a SudokuRegion class.
Don't extend ArrayList. If you did, that would imply that the essense of a SudokuCell is a List. But a SudokuCell, at its core, is really just a holder of a single value. The ArrayList is auxiliary to that central purpose, so just give each SudokuCell its own ArrayList.
> I think I can make the methods in SudokuGame also static, they don't > need to be instantiated at this time, perhaps if I invent a solution > method that is recursive? Keep in mind, methods can not be instantiated. I don't think a recursive solution would depend on whether the methods were static or not. You can definitely write recursive solutions of both forms:
class Test { // not tested! public static int factorialOne(int n) { if (n>1) return n * Test.factorialOne(n-1); else return 1; } public int factorialTwo(int n) { if (n>1) return n * this.factorialTwo(n-1); else return 1; } }
Notice that in this particular case, static makes more sense because the method doesn't use any data from the "this" object.
> I'm also toying with making the entire sudokuBoard a static variable so > that I don't have to keep passing and returning it to the various > methods in the SudokuGame class that I want to operate on the board. This isn't ideal. If you do that, then you're designing the code so that only one SudokuBoard exists. Despite not comporting with reality, it also limits you if you ever try to add the functionality for a 2nd board down the road. In general you want to avoid getting yourself into these corners; instead, code for the most general case when feasible. Especially if you ever write code professionally, you'll find that bosses are rarely sympathetic with the "But the code isn't written to do that! I'd have to start from scratch!" excuse.
> Again, I hope this is clear and I appreciate any feedback on the design > I've got (I don't mind changing it, after all I'm only doing it to > learn). This sounds like a very good exercise to me. Keep in mind that there's generally not a "right way" -- only subjective judgments on the various approaches available...you could write this entire program procedurally, but the idea behind good OO design is to make code more readable, more maintainable and more reusable.
|\/| /| |2 |< mehaase(at)gmail(dot)com
Mike - 13 Dec 2005 15:17 GMT Mark, I sent a reply to your message, but it never made the newsgroup. Could it be that I should not quote your posts? I see that your posts are not marked for archiving, perhaps that I quoted it caused a problem?
Mike
Mark Thomas - 13 Dec 2005 17:08 GMT > Mark, I sent a reply to your message, but it never made the newsgroup. > Could it be that I should not quote your posts? I see that your posts > are not marked for archiving, perhaps that I quoted it caused a > problem? > > Mike Hi Mike - I'm not aware of any difference between my posts and others, but then I'm no expert in the mysteries of usenet. I had to give up on one email address due to spam, but if you need to write to me use mark at highland dot f9 dot co dot uk.
Mark
Mike - 13 Dec 2005 18:44 GMT > > Mark, I sent a reply to your message, but it never made the newsgroup. > > Could it be that I should not quote your posts? I see that your posts [quoted text clipped - 5 lines] > one email address due to spam, but if you need to write to me use mark > at highland dot f9 dot co dot uk. My apologies. I was addressing Mark Haase.
Mike
Roedy Green - 11 Dec 2005 20:03 GMT >Based on what you showed me, I went back to my textbook and re-read the >bits about static methods and variables. Basically, what I understand >is that a non-static method must be instantiated (as you did) before it >can be used. Alternatively, I can make the method static and then I >don't have to instantiate it. not quite.
Let's say you had a TV class. There are two kinds of variables static variable that track facts about all televisions, e.g. total sold, a list of manufacturers, and facts about individual televisions, e.g. manufacturer, serial number, diagonal, type LCD/CRT...
The facts about televisions in general are stored in static variables, one per class. The facts about individual televisions are stored in TV objects instantiated with new in instance variables.
Similarly there are static methods about televisions in general and instance methods about particular televisions.
The terminology is you instantiate an object, then you can call the instance methods on it. You don't instantiate methods.
 Signature Canadian Mind Products, Roedy Green. http://mindprod.com Java custom programming, consulting and coaching.
Roedy Green - 11 Dec 2005 20:16 GMT On Sun, 11 Dec 2005 20:03:32 GMT, Roedy Green <my_email_is_posted_on_my_website@munged.invalid> wrote, quoted or indirectly quoted someone who said :
>Let's say you had a TV class. There are two kinds of variables static >variable that track facts about all televisions, e.g. total sold, a [quoted text clipped - 7 lines] >Similarly there are static methods about televisions in general and >instance methods about particular televisions. let me try that again, quoting from http://mindprod.com/jgloss/class.html
Let's say you had a TV class to deal with television sales. There are two kinds of variables:
1. static variables that track facts about all televisions in general, e.g. total sold or a list of manufacturers.
2. instance (non-static) variables that track facts about individual televisions, e.g. manufacturer, serial number, diagonal, type LCD/CRT etc.
The facts about televisions in general are stored in static variables, only one copy of the variable for the whole TV class. The facts about individual televisions are stored in instance variables TV objects instantiated with new. There is one copy of each instance field per TV object.
Similarly, there are static methods about televisions in general and instance methods about particular televisions. Unless you have a TV object, you can't call any of the instance methods. You don't need a TV object to call one of the TV static methods.
 Signature Canadian Mind Products, Roedy Green. http://mindprod.com Java custom programming, consulting and coaching.
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|