I have a Sudoku puzzle solver that requires us to use recursion.. The problem is my boolean to check for available space is supposed to update the current position by reference and it is not. What would cause this?
public boolean solve()
{
Coordinate current = new Coordinate();
if (findEmptyGridSlot(current)) { // THE ERROR IS HERE ********** THIS IS SHOWING (0,0) STILL ******************
for (int number = 1; number <= 9; number++)
if (canPlaceNumber(current, number)) {
grid[current.getRow()][current.getColumn()] = number;
if (solve())
return true;
grid[current.getRow()][current.getColumn()] = 0;
} return false;
}else
return true;
}
private boolean findEmptyGridSlot(Coordinate coordinate)
{
boolean found = false;
try{
while (!found)
{
if (grid[coordinate.getRow()][coordinate.getColumn()] == 0)
found = true;
else
coordinate = coordinate.next(); // *****This is supposed to update the current coordinate ******
}
}catch (Exception e){
//CREATE No Empty Cells Exception
}
return found;
}
public Coordinate next()
{
Coordinate result = new Coordinate(row, column);
result.column++;
if (result.column > MAX_COORDINATE)
{
result.column = MIN_COORDINATE;
result.row++;
if (result.row > MAX_COORDINATE) result = null;
}
return result;
}
Java passes by value. This means you are getting a copy of the reference to coordinate. If you point that copy to a new object (i.e. coordinate = coordinate.next) you are only changing the local copy. Now, on the other hand, if you changed an attribute of the object your variable refers to (e.g. coordinate.x = foo or coordinate.setX(foo)) that change will be visible to the caller of your method.
jpm is correct, but I misread the first time so i'm going to try to clarity
private boolean findEmptyGridSlot(Coordinate coordinate)
A reference is passed by value. Think in these terms "coordinate" is a box that holds a piece of paper, on the piece of paper an address is written. coordinate is a box that belongs to only this method and it has its own piece of paper (many pieces of paper may have the same address written on them)
We can look in this box and 'post' things to the address written on the piece of paper, however when we say
coordinate=something
this means write on a new piece of paper the address of 'something'. Throw away the old piece of paper.
This action in no way affects the original 'house' that the first piece of paper had the address on. When my friend Jon updates his address book it doesn't matter what he writes, I still live in my house.
So, if coordinate has some easy substructure (eg x and y) you can 'post' an instruction to change x and y to be equal to the "next" one.
Or as a hack you can enclose a Coordinate inside annother object so you can post an instruction to it to change what the hack class points to
Test Code refered to in comments:
public class Test {
public static void main(String args[]){
String bareMinObject="start";
changeString(bareMinObject);
System.out.println(bareMinObject); //Prints start, change string has no effect
}
public static void changeString(String input){
String temp="end";
input=temp;
}
}
Related
As a fairly green Java coder I've set myself the hefty challenge of trying to write a simple text adventure. Unsurprisingly, I've encountered difficulties already!
I'm trying to give my Location class a property to store which exits it contains. I've used a boolean array for this, to essentially hold true/false values representing each exit. I'm not entirely convinced that
a) this is the most efficient way to do this and
b) that I'm using the right code to populate the array.
I would appreciate any and all feedback, even if it is for a complete code over-haul!
At present, when instantiating a Location I generate a String which I send through to the setExits method:
String e = "N S U";
secretRoom.setExits(e);
In the Location class, setExits looks like this:
public void setExits(String e) {
if (e.contains("N"))
bexits[0] = true;
else if (e.contains("W"))
bexits[1] = true;
else if (e.contains("S"))
bexits[2] = true;
else if (e.contains("E"))
bexits[3] = true;
else if (e.contains("U"))
bexits[4] = true;
else if (e.contains("D"))
bexits[5] = true;
}
I'll be honest, I think this looks particularly clunky, but I couldn't think of another way to do it. I'm also not entirely sure now how to write the getExits method...
Any help would be welcome!
The most efficient and expressive way is the following:
Use enums as Exits and use an EnumSet to store them. EnumSet is an efficient Set implementation that uses a bit field to represent the enum constants.
Here is how you can do it:
public enum Exit { North, West, South, East, Up, Down; }
EnumSet<Exit> set = EnumSet.noneOf(Exit.class); // An empty set.
// Now you can simply add or remove exits, everything will be stored compactly
set.add(Exit.North); // Add exit
set.contains(Exit.West); // Test if an exit is present
set.remove(Exit.South); //Remove an exit
Enum set will store all exits in a single long internally, so your code is expressive, fast, and saves a lot of memory.
Is there any reason why you are doing this with Strings and aren't passing in booleans, i.e.
public void setExits(boolean N, boolean E, boolean S, boolean W, boolean U, boolean D)
Or having setters?
public void setNorthOpen(boolean open)
{
bexits[4] = open;
}
Secondly, why are you storing the exits as an array of booleans, it's a small finite set, why not just
boolean N,S,E,W,U,D;
As then you don't need to keep track of which number in the array each direction is.
Also
This is a correct answer (if not completely optimal like that of #gexicide) but I fully encourage anyone to look at the other answers here for an interesting look at how things can be done in Java in different ways.
For future reference
Code which works belongs on Code Review, not Stack Overflow. Although as #kajacx pointed out, this code shouldn't -in fact- work.
OK, first of all, your setExits() method will not work as intended, chained if-elseif will maximally execute 1 branch of code, for example:
if (e.contains("N"))
bexits[0] = true;
else if (e.contains("W"))
bexits[1] = true;
Even if e contains both N and W, only bexits[0] will be set. Also this method will only add exits (for example calling setExits("") will not delete any existing exits.
I would change that method to:
bexits[0] = e.contains("N");
bexits[1] = e.contains("W");
...
Also, i definetly wouldn't remember that north is on index 0, west in on 1, ... so a common practice is to name your indexes using final static constants:
public static final int NORTH = 0;
public static final int WEST = 1;
...
Then you can write in your setExits method:
bexits[NORTH] = e.contains("N");
bexits[WEST] = e.contains("W");
...
(much more readible)
Finally, if you want your code even more well-arranged, you can make a Exits class representing avaliable exits, and backed by boolean array. Then on place where you create your String, you could create this class instead and save yourself work with generating and then parsing a string.
EDIT:
as #gexicide answers, there is a really handy class EnumSet which would be probably better for representing the exits than bollean array.
The EnumSet in the other answer is the best way to do this, I just wanted to add one more thing though for the future when you start looking not just at whether you can move but where you are moving to.
As well as EnumSet you also have EnumMap.
If you define a Room class/interface then inside the Room class you can have
Map<Direction, Room> exits = new EnumMap<>(Direction.class);
You can now add your links into the map as follows:
exits.put(Direction.NORTH, theRoomNorthOfMe);
Then your code to move between rooms can be very general purpose:
Room destination=currentRoom.getExit(directionMoved);
if (destination == null) {
// Cannot move that way
} else {
// Handle move to destination
}
I would create an Exit enum and on the location class just set a list of Exit objects.
so it would be something like:
public enum Exit { N, S, E, W, U, D }
List<Exit> exits = parseExits(String exitString);
location.setExits(exits);
Given what your code looks like, this is the most readable implementation I could come up with:
public class Exits {
private static final char[] DIRECTIONS = "NSEWUD".toCharArray();
public static void main(String... args) {
String input = "N S E";
boolean[] exits = new boolean[DIRECTIONS.length];
for(int i = 0; i< exits.length; i++) {
if (input.indexOf(DIRECTIONS[i]) >= 0) {
exits[i] = true;
}
}
}
}
That being said, there's a number of cleaner solutions possible. Personally I would go with enums and an EnumSet.
By the way, your original code is incorrect, as it will set as most one value in the array to true.
If you're defining exits as a string, you should use it. I would do it like:
public class LocationWithExits {
public static final String NORTH_EXIT="[N]";
public static final String SOUTH_EXIT="[S]";
public static final String EAST_EXIT="[E]";
public static final String WEST_EXIT="[W]";
private final String exitLocations;
public LocationWithExits(String exitLocations) {
this.exitLocations = exitLocations;
}
public boolean hasNorthExit(){
return exitLocations.contains(NORTH_EXIT);
}
public static void main(String[] args) {
LocationWithExits testLocation=new LocationWithExits(NORTH_EXIT+SOUTH_EXIT);
System.out.println("Has exit on north?: "+testLocation.hasNorthExit());
}
}
using array of booleans might cause a lot of problems if you forget what exactly means bexits[0]. Os it for north or south? etc.
or you can just use enums and list of exits available . Then in methid test if list contain a certain enum value
Personally, I think you can hack it around a bit using an enum and turn the following:
public void setExits(String e) {
if (e.contains("N"))
bexits[0] = true;
else if (e.contains("W"))
bexits[1] = true;
else if (e.contains("S"))
bexits[2] = true;
else if (e.contains("E"))
bexits[3] = true;
else if (e.contains("U"))
bexits[4] = true;
else if (e.contains("D"))
bexits[5] = true;
}
into
public enum Directions
{
NORTH("N"),
WEST("W"),
SOUTH("S"),
EAST("E"),
UP("U"),
DOWN("D");
private String identifier;
private Directions(String identifier)
{
this.identifier = identifier;
}
public String getIdentifier()
{
return identifier;
}
}
and then do:
public void setExits(String e)
{
String[] exits = e.split(" ");
for(String exit : exits)
{
for(Directions direction : Directions.values())
{
if(direction.getIdentifier().equals(exit))
{
bexits[direction.ordinal()] = true;
break;
}
}
}
}
Although after having written it down, I can't really tell you if it's that much better. It's easier to add new directions, that's for sure.
All the approaches listed in the answeres are good. But I think the approach you need to take depends on the way you are going to use the exit field. For example if you are going to handle exit as strings then Ross Drews approach would require a lot of if-else conditions and variables.
String exit = "N E";
String[] exits = exit.split(" ");
boolean N = false, E = false, S = false, W = false, U = false, D = false;
for(String e : exits){
if(e.equalsIgnoreCase("N")){
N = true;
} else if(e.equalsIgnoreCase("E")){
E = true;
} else if(e.equalsIgnoreCase("W")){
W= true;
} else if(e.equalsIgnoreCase("U")){
U = true;
} else if(e.equalsIgnoreCase("D")){
D = true;
} else if(e.equalsIgnoreCase("S")){
S = true;
}
}
setExits(N, E, S, W, U, D);
Also if you have an exit and you want to check whether a location has that particular exit then again you will have to do the same
public boolean hasExit(String exit){
if(e.equalsIgnoreCase("N")){
return this.N; // Or the corresponding getter method
} else if(e.equalsIgnoreCase("E")){
return this.E;
} else if(e.equalsIgnoreCase("W")){
return this.W;
} else if(e.equalsIgnoreCase("U")){
return this.U;
} else if(e.equalsIgnoreCase("D")){
return this.D;
} else if(e.equalsIgnoreCase("S")){
return this.S;
}
}
So if you are going to manipulate it as a string, in my opinion the best approach would be to go for list and enum. By this way you could do methods like hasExit, hasAnyExit, hasAllExits, hasNorthExit, hasSouthExit, getAvailableExits etc etc.. very easily. And considering the number of exits (6) using a list (or set) wont be an overhead. For example
Enum
public enum EXIT {
EAST("E"),
WEST("W"),
NORTH("N"),
SOUTH("S"),
UP("U"),
DOWN("D");
private String exitCode;
private EXIT(String exitCode) {
this.exitCode = exitCode;
}
public String getExitCode() {
return exitCode;
}
public static EXIT fromValue(String exitCode) {
for (EXIT exit : values()) {
if (exit.exitCode.equalsIgnoreCase(exitCode)) {
return exit;
}
}
return null;
}
public static EXIT fromValue(char exitCode) {
for (EXIT exit : values()) {
if (exit.exitCode.equalsIgnoreCase(String.valueOf(exitCode))) {
return exit;
}
}
return null;
}
}
Location.java
import java.util.ArrayList;
import java.util.List;
public class Location {
private List<EXIT> exits;
public Location(){
exits = new ArrayList<EXIT>();
}
public void setExits(String exits) {
for(char exitCode : exits.toCharArray()){
EXIT exit = EXIT.fromValue(exitCode);
if(exit != null){
this.exits.add(exit);
}
}
}
public boolean hasExit(String exitCode){
return exits.contains(EXIT.fromValue(exitCode));
}
public boolean hasAnyExit(String exits){
for(char exitCode : exits.toCharArray()){
if(this.exits.contains(EXIT.fromValue(exitCode))){
return true;
}
}
return false;
}
public boolean hasAllExit(String exits){
for(char exitCode : exits.toCharArray()){
EXIT exit = EXIT.fromValue(exitCode);
if(exit != null && !this.exits.contains(exit)){
return false;
}
}
return true;
}
public boolean hasExit(char exitCode){
return exits.contains(EXIT.fromValue(exitCode));
}
public boolean hasNorthExit(){
return exits.contains(EXIT.NORTH);
}
public boolean hasSouthExit(){
return exits.contains(EXIT.SOUTH);
}
public List<EXIT> getExits() {
return exits;
}
public static void main(String args[]) {
String exits = "N E W";
Location location = new Location();
location.setExits(exits);
System.out.println(location.getExits());
System.out.println(location.hasExit('W'));
System.out.println(location.hasAllExit("N W"));
System.out.println(location.hasAnyExit("U D"));
System.out.println(location.hasNorthExit());
}
}
Why not this if you want a shorter code:
String symbols = "NWSEUD";
public void setExits(String e) {
for (int i = 0; i < 6; i++) {
bexits[i] = e.contains(symbols.charAt(i));
}
}
If you want a generic solution you can use a map, which maps from a key (in your case W, S, E.. ) to a corresponding value (in your case a boolean).
When you do a set, you update the value the key is associated with. When you do a get, you can take an argument key and simply retrieve the value of the key. This functionality does already exist in map, called put and get.
I really like the idea of assigning the exits from a String, because it makes for brief and readable code. Once that's done, I don't see why you would want to create a boolean array. If you have a String, just use it, although you might want to add some validation to prevent accidental assignment of strings containing unwanted characters:
private String exits;
public void setExits(String e) {
if (!e.matches("[NSEWUD ]*")) throw new IllegalArgumentException();
exits = e;
}
The only other thing I would add is a method canExit that you can call with a direction parameter; e.g., if (location.canExit('N')) ...:
public boolean canExit(char direction) {
return exits.indexOf(direction) >= 0;
}
I like enums, but using them here seems like over-engineering to me, which will rapidly become annoying.
**Edit**: Actually, don't do this. It answers the wrong question, and it does something which doesn't need to be done. I just noticed #TimB's answer of using a map (an EnumMap) to associate directions with rooms. It makes sense.
I still feel that if you only need to track exit existence, a String is simple and effective, and anything else is over-complicating it. However, only knowing which exits are available isn't useful. You will want to go through those exits, and unless your game has a very plain layout it won't be doable for the code to infer the correct room for each direction, so you'll need to explicitly associate each direction with another room. So there seems to be no actual use for any method "setExits" which accepts a list of directions (regardless of how it's implemented internally).
public void setExits(String e)
{
String directions="NwSEUD";
for(int i=0;i<directions.length();i++)
{
if(e.contains(""+directions.charAt(i)))
{
bexits[i]=true;
break;
}
}
}
the iterative way of doing the same thing..
Long chains of else if statements should be replaced with switch statements.
Enums are the most expressive way to store such values as long as the efficiency is not a concern. Keep in mind that enum is a class, so creation of a new enum is associated with corresponding overhead.
Basicly I am creating a game that you click on falling objects, E.G cookies, and I need to know how to check and see if a certain cookie has been pressed so it can disappear but the problem is that its in an array.
Here is a bit of my code:
Input class...
public class Input implements MouseListener, MouseMotionListener{
#Override
public void mousePressed(MouseEvent e) {
if(e.getSource().equals(MainGame.CG)){
if(MainGame.MG.inGame){
//There is actually something else here but its classified (haha sorry about that)
if(e.getPoint().x > /*I NEED SOMETHING HERE*/){
//tells you if the object has been pressed
MainGame.CG.cookieClicked = true; //CG = ClickerGame
}
}
}
}
}
class with array...
public class ClickerGame extends JPanel{
public int amount;
public FallingObject[] fo = new FallingObject[120]; //THE ARRAY I'M HAVING TROUBLES WITH
/*THE REST IS A SECRET (SORRY ABOUT THAT)*/
}
If you don't understand here is a picture to demonstrate what I need...
In order to avoid having to check the coordinates of 120 different items on each click, make every element inside FallingObject[] aware of three things:
Its own area of influence (see sn00fy's answer)
The containing class (in this case probably ClickerGame
Its location in the array (an int)
To do this, you would need to change your FallingObject constructor to look something like this:
public void FallingObject(ClickerGame master, int index); //add whatever else is needed for Falling Object.
Then you could instantiate the array as follows.
for(int i = 0; i < 120; i++) {
fo[i] = new FallingObject(this, i ); //add anything else needed for the constructor
}
Then each FallingObject is responsible for its own state, and when clicked it is able to report back to the ClickerGame instance. All you need now is a method in ClickerGame which each FallingObject can call.
public void clickedObj(int index) {
FallingObject temp = null;
if(index >= 0 && index < 120) {
temp = fo[index];
//Do stuff with temp :)
}
}
To call this method from within FallingObject just reference the 'master' variable (which you should probably save as a global variable within the class.
You have to check every element in your FallingObject[] array if it intersects with the mouse pointer coordinates at the moment of the click.
You can implement a simple rectangle test or use a circle for each cookie as explained here:
Equation for testing if a point is inside a circle
I have some code that creates Objects called Weights. Now there are subclasses of these Weights called - WeightSmall, WeightMedium, and WeightLarge - each with their own static variable called onScreen. This variable should increment when one of either WeightSmall, WeightMedium or WeightLarge is added, however these get return on the call of the create method rather than being added to an array. I have an array of Weight objects - is there a way to access what subclass type an element is in the array of the parent class?
Here is the code for creating weights:
public Weight createWeight() {
decider = Math.random() * 1;
// creates rocks randomly with the lowest chance for l, and the highest chance for m
if (decider <= 0.33) {
// small weight
return new WeightSmall(BitmapFactory.decodeResource(getResources(), R.drawable.weight_s), new Random().nextInt(screenWidth), -10);
} else if (decider <= 0.5 && decider > 0.33) {
// large weight
return new WeightLarge(BitmapFactory.decodeResource(getResources(), R.drawable.weight_l), new Random().nextInt(screenWidth), -10);
} else {
// medium weight
return new WeightMedium(BitmapFactory.decodeResource(getResources(), R.drawable.weight_m), new Random().nextInt(screenWidth), -10);
}
}
What needs to happen is for WeightSmall lets say, it needs to check WeightSmalls onScreen variable to see if it's smaller than, let's say 3. if it is return the weight. However I can't think of a way to access WeightSmall's onScreen variable as it needs to be created more than once and I tried implement them into an ArrayList but it causes complications in the update method. Here is the rest of the code (that matters) for the class:
public void render(Canvas canvas) {
if (canvas != null) {
canvas.drawColor(Color.WHITE);
player.draw(canvas);
Weight[] weightArray = weights.toArray(new Weight[0]);
for (Weight weight : weightArray) {
weight.draw(canvas);
}
}
}
// updates the weight's position on the screen and checks collision with the player
public void update() {
Weight[] weightArray = weights.toArray(new Weight[0]);
for (Weight weight : weightArray) {
weight.update();
if (weight.getBounds().intersect(player.getBounds())) {
player.setTouched(false);
Intent gameOverIntent = new Intent(this.getContext(), GameOverActivity.class);
this.getContext().startActivity(gameOverIntent);
((Activity) getContext()).finish();
}
}
}
// count down timer spawning weights in every tick
public void timer() {
if (start == true) {
if (weightSpawnTimer != null) {
weightSpawnTimer.cancel();
weightSpawnTimer = null;
}
weightSpawnTimer = new CountDownTimer(30000, 800) {
public void onTick(long millisUntilFinished) {
weights.add(createWeight());
}
public void onFinish() {
weightSpawnTimer.start();
}
}.start();
}
}
Edit for clarity: What I need to happen, is in the onTick method, check if the subclass of weight's onScreen variable is <= 3, if it is, create a new weight, if it isn't do nothing. Once the weight is then offscreen, decrement this variable so new weights of that subclass can then be created.
What about
class WeightSmall {
public WeightSmall(...) {
// increment static
}
}
Let each class be responsible to increment it's own number in case an instance is created.
Modifying a static variable from an instance is usually considered bad practice. The few legit use-cases are typically some sort of instance counting. At least when you don't count down.
Counting down is where the trouble starts because Objects do have a defined start but their end is not guaranteed. You can count down in finalize - i.e. when the garbage collector has found your instance - but that's not guaranteed to happen soon or at all. Using that to find out how many instances are on screen would correlate to the actual number but could be completely wrong.
So in a case when you want to know how many objects you show on screen you must actively count that number down once the place responsible for showing the objects let's go of one.
And since that is already a responsibility for the class that wants to know how many objects are on screen, it should as well keep track of the numbers in a local variable of it's own.
By using a static property you limit yourself to have just 1 screen. If you let the other place count the number you don't limit yourself.
Static variable initialized at 0, then on the constructor your make it +1
I'm working on a text-based adventure game and I'm trying to externalise as much of the setup as possible so that I can work with a friend who wants to write the storyline. I have three classes so far. A room class with a title, description, and an array of Exits. Also an Exit class with the following constructor.
public Exit(int direction, Room connection);
Exits also have public int variables referring to the different directions:
public static final int NORTH = 0;
This is all so I can set up an exit on a room by saying:
Room r = new Room("Title","Description");
Room r2 = new Room("Title", "Description");
r.addExit(new Exit(Exit.NORTH, r2);
This would make an exit on the room r that is on the north side and leads to the room r2. Now for the externalisation I'm trying to make a .txt file where I can simply put the current room number, the exit direction (string), and the room number it leads to.
I can do this just fine as far as reading the file goes but where I'm struggling is when I'm setting up the direction, I can't say
Exit. /*String read from file*/
So how can I access those public integers from the Exit class using a string from the txt file?
Try using an enum instead.
public enum ExitDirection { NORTH = 0, … };
ExitDirection foo = ExitDirection.valueOf (stringFromFile);
…else, you'll just have to bite the bullet with something like
if (stringFromFile.equals("NORTH")) { foo = NORTH; }
else if (stringFromFile ... (ad nauseum)
The quick and dirty fix is to implement a method to do string comparison and return the appropriate constant. But you should also consider using an enum as suggested by BRPocock, it's a much cleaner way to do it.
int directionFromStr(String str) {
// Putting the string constant on the left side of the expression guards against null input
if ("NORTH".equalsIgnoreCase(str)) return Exit.NORTH;
if ("SOUTH".equalsIgnoreCase(str)) return Exit.SOUTH;
if ("EAST".equalsIgnoreCase(str)) return Exit.EAST;
if ("WEST".equalsIgnoreCase(str)) return Exit.WEST;
// You could also return -1 or something like that
throw new IllegalArgumentException("bad direction");
}
I have a bit of a problem. I'm making a Finite Automata checker.
Given an input, and the DFA, does it end on a accepting state.
My problem is creating a new DFA_State from another's target.
DFA_State state0, state1, curr_state, init_state, temp; //fine, I think
state0 = new DFA_State();
state1 = new DFA_State();
state0 = new DFA_State("State 0",true, state0, state1); //fine, I think
init_state = new DFA_State(state0); //fine, I think
but, this bit is throwing up problems.
temp = new DFA_State(curr_state.nextState(arr1[i]));
*
*
curr_state = new DFA_State(temp);
Thanks for any help,
Dave
Edit:
God I was retarded when I did this, AFAIK, I just wasn't thinking straight, added methods to set the values to the DFA_State object.
//in DFA_State class
public void set(DFA_State on_0, DFA_State on_1, Boolean is_accepting, String name){
this.on_0 = on_0;
this.on_1 = on_1;
this.is_accepting = is_accepting;
this.name = name;
}
//in main
DFA_State state0, state1, curr_state;
state0 = new DFA_State();
state1 = new DFA_State();
state0.set(state0, state1, false, "State 0");
state1.set(state1, state0, true, "State 1");
curr_state = state0;//initial state
//iterate across string input changing curr_state depending on char c
curr_state = getNextState(c);
//at end
if(curr_state.isAccepting())
System.out.println("Valid, " + curr_state.getName() + " is accepting);
else
System.out.println("Invalid, " + curr_state.getName() + " is not accepting);
In that first line, you declare the variables state0, state1, curr_state, init_state and temp as being variables of type DFA_State. However, that only declares them, they are not yet initialized. The next few lines are all okay. Second line creates a state without anything in it and assigns it to state0, so does the third line for state1. Fourth line overwrites your previous state0 assignment with a new DFA_State that has actual contents. Fifth line creates a DFA_State as a copy of state0 and assigns it to init_state.
Assuming there's nothing in between this and the first line of your second code block, now you'll get a problem. You're assigning temp with a new DFA_State that uses a copy-constructor with an argument relying on curr_state. But at that point, that variable hasn't been initialized yet. Just because it was declared doesn't mean it has somehow already been structured in memory. When you call nextState on it, there's simply no variable to resolve this to. Don't expect to get something like a pointer that will eventually point to a part of what you put in curr_state.
I'm just guessing, but from your code style I'd say you have a background in C or C++. Look into the differences between those languages and Java. If possible, I'd also advise you to make your DFA_State class immutable, since this is more reliable and will avoid mistakes. That means getting rid of the no-args constructor. Here's a reworking of it (not actually compiled, might contain errors):
package foundations.of.computing;
/**
*
* #author Kayotic
*/
class DFA_State {
private final String state;
private final DFA_State on_0;
private final DFA_State on_1;
private final boolean isAccepting;
//private DFA_State dummy;
public DFA_State(DFA_State arg) {
//this(arg.is_accepting(), arg.on0(), arg.on1());
state = arg.get_name();
isAccepting = arg.is_accepting();
on_0 = arg.on0();
on_1 = arg.on1();
}
public DFA_State(String name, Boolean accepting, DFA_State on0, DFA_State on1) {
state = name;
isAccepting = accepting;
on_0 = on0;
on_1 = on1;
}
public String get_name(){
return state;
}
public Boolean is_accepting() {
return isAccepting;
}
public DFA_State on0() {
return on_0;
}
public DFA_State on1() {
return on_1;
}
public DFA_State nextState(char i) {
if (i == '0') {
return on0();
} else if (i == '1') {
return on1();
} else {
System.out.println("Error with input");
return null;
}
}
}
Even if you can't make the instance variables final, it's best to at least make them private, since you already have methods for getting them.
There are better memory representations of DFAs than the object-oriented.
You should use a simple lookuptable:
int[] table = new int[vocabularyCount][stateCount];
Every State and every word gets a number, starting with 0.
Fill the table with the state transitions, or -1, if there is no transition. Now you just need the translation methods for the states and the words.
Heres a generic DFA algorithm:
public boolean checkSentence(String s, int[] finishes) {
// fill table
int state = 0; // assuming S0 is the start state
for (int i = 0; i < s.length(); i++) {
state = table[translate(s.charAt(i))][s];
}
for (int i = 0; i < finishes.length; i++) {
if (finishes[i] == state) {
return true;
}
}
return false;
}
The program is quite poorly written. Look at this in your FoundationsOfComputing.java:
state0 = new DFA_State();
state1 = new DFA_State();
state0 = new DFA_State("State 0",true, state0, state1);
You essentially created 3 instances of state - two instances which are not initialized (first two lines in your code) - all their instance variables are null.
Then you create the third instance, which you point to the first two uninitialized ones, and assign it to state0 variable. Please note, at this point, it is only the value of the variable that changes, not the values you passed in the DFA-State constructor!!! So, what you now have in state0 is a state that points to two uninitialized states.
Now let's look at the code further down in the FoundationsOfComputing.java:
while (i < arr1.length) {//loops through array
System.out.println(i + ". scan shows " + arr1[i]);
temp = new DFA_State(curr_state.nextState(arr1[i]));
System.out.println(" "+curr_state.get_name()+ " moves onto " + temp.get_name());
curr_state = new DFA_State(temp);
i++;
}
I am guessing this throws NullPointerException - that code moves to the on_0 state of state0 - which is a state that has not been initialized (all it's instance variables are null), so in the following pass of the loop, when it calls curr_state.nextState(whatever), it would return null and you are trying to pass that to the copy-constructor which would result in NPE.
Ok so we know this is homework. Let's do this instead of telling you the answer let's try and work through it on your own. If you are seeing a NullPointerException (NPE). Grab the second line of the exception:
java.lang.NullPointerException: null
at com.blah.blah.SomeObject.someMethod(SomeArgumentType):1234 <<< here
....
That 1234 is the line number in the file that contains SomeObject. If you goto that line number you can see exactly where the NPE is being generated from. For example if line 1234 was:
this.foo = bar.indexOf("caramel");
You can easily deduce what was null. No clue? Well this can never be null so this.foo isn't the problem. If this could be null you couldn't be inside that method because this points to the instance you are currently within. Therefore, the only other statement where a variable is being dereferenced is bar so bar must be null. Let's look at your code:
temp = new DFA_State(curr_state.nextState(arr1[i]));
Say you find out the line above is tossing an exception. Well there could be several things that could be null. curr_state could be null, or arr1 could be null in which case this line would blow up. However, if arr1[i] is null or curr_state.nextState() is returning null then you won't see the NPE pointing at this line, but would be coming out of the constructor should someone try to call methods on that method parameter.
Hopefully, this will give you the tools you need to track down problems in your application by understanding exception stack traces.