NPE in line invoking equals() - java

Sorry if this all seems hard to understand but I am new to programming and I have looked in several books and websites and from my understanding what I am trying to do should work. The assignment I am working on is classes calling classes. Without putting all my code in here I will try to be as specific as possible in unclear areas. The null pointer exception is for this particular line of code:
if(CDList[i].getArtist().equals(artist) == true)
//CDList is an array of CD objects (which are created in another class)
//getArtist() is a method of the CD class which returns a String
//the artist in the equals() is the Scanner object the user has inputed, also a String
The point of this particular method is to search through the array CDList and compare the artist String stored to the artist String scanned in and then the same for the title. If found then the contents of that portion of the array will be deleted. Here is the rest of the method if it will help:
void delete()
{
Scanner input = new Scanner(System.in);
System.out.println("Enter artist and title to be deleted: ");
String artist = input.nextLine();
String title = input.nextLine();
for(int i = 0; i <= numOfCDs; i++)
{
if(CDList[i].getArtist().equals(artist) == true)
{
for(int j = 0; j <= numOfCDs; j++)
{
if(CDList[j].getTitle().equals(title) == true)
{
System.out.println("Found CD: " + CDList[j].getArtist() + " " +
CDList[j].getTitle());
System.out.println("Would you like to delete it? Y/1 N/0 ");
if(input.nextInt() == 1)
{
CDList[j] = null;
numOfCDs--;
}
}
else
System.out.println("CD not found.");
}
}
else
System.out.println("CD not found.");
}
}
Sorry, here is the rest of the code. Just thought it was so much I'd leave it out.
CD Class:
package assignment3;
public class CD
{
public String artist;
public String title;
private tracklist listOfTracks = new tracklist();
CD(String artistName, String titleName)
{
artist = artistName;
title = titleName;
}
public String getArtist()
{
return artist;
}
public String getTitle()
{
return title;
}
public boolean addTrack(String trackInfo)
{
boolean result = false;
if(listOfTracks.add(trackInfo) == true)
result = true;
return result;
}
public int numTracks()
{
int count = listOfTracks.count();
return count;
}
public void display()
{
System.out.println(" ");
System.out.println(getArtist() + " : " + getTitle());
listOfTracks.display(7);
}
}
trackList Class:
package assignment3;
public class tracklist
{
public String[] tracks;
public int numElements;
tracklist()
{
tracks = new String[99];
numElements = 0;
}
public boolean add(String track)
{
boolean result = true;
int index = 0;
while(tracks[index] != null)
{
index++;
}
tracks[index] = track;
numElements++;
if(numElements > 99)
result = false;
return result;
}
public int count()
{
return numElements;
}
public void display(int indent)
{
for(int i = 1; i < numElements; i++)
{
System.out.print(i);
if(i >= 10)
{
for(int j = 0; j < (indent - 1); j++)
{
System.out.print(" ");
}
}
else
{
for(int j = 0; j < indent; j++)
{
System.out.print(" ");
}
}
System.out.println(tracks[i]);
}
}
}
CDList Class:
package assignment3;
import java.util.Scanner;
public class CDList
{
public int numOfCDs;
private CD[] CDList;
private int front,rear;
CDList(int size)
{
CDList = new CD[size];
numOfCDs = 0;
front = 0;
rear = size - 1;
}
boolean add()
{
boolean result;
Scanner input = new Scanner(System.in);
System.out.println("Enter the Artist Name and CD Title: ");
CD userCD = new CD(input.nextLine(), input.nextLine());
System.out.println("Enter the number of tracks: ");
int trackNumber = input.nextInt();
System.out.println("Enter your track titles: ");
for(int i = 0; i <= trackNumber; i++)
{
userCD.addTrack(input.nextLine());
}
if(rear == front)
result = false;
else
{
if(CDList[rear] != null)
rear--;
else
CDList[rear] = userCD;
result = true;
}
return result;
}
void delete()
{
Scanner input = new Scanner(System.in);
System.out.println("Enter artist and title to be deleted: ");
String artist = input.nextLine();
String title = input.nextLine();
for(int i = 0; i <= CDList.length - 1; i++)
{
if((CDList[i].getArtist().equals(artist)) &&
(CDList[i].getTitle().equals(title)))
{
System.out.println("Found CD of: " + CDList[i].getArtist() + " " +
CDList[i].getTitle());
System.out.println("Would you like to delete it? Y/1 N/0 ");
if(input.nextInt() == 1)
{
CDList[i] = null;
numOfCDs--;
}
}
else
System.out.println("CD not found.");
}
}
void SortArtist()
{
CD temp = new CD(" ", " ");
for(int i = 0; i < numOfCDs; i++)
if(CDList[i].getArtist().compareTo(CDList[i + 1].getArtist()) < 0)
{
temp = CDList[i];
CDList[i] = CDList[i + 1];
CDList[i + 1] = temp;
}
}
void SortTitle()
{
CD temp = new CD(" ", " ");
for(int i = numOfCDs; i > 0; i--)
{
int x = 0;
for(int j = 1; j <= i; j++)
{
if(CDList[i].getTitle().compareTo(CDList[i + 1].getTitle()) < 0)
x = j;
}
temp = CDList[x];
CDList[x] = CDList[i];
CDList[i] = temp;
}
}
void Display()
{
for(int i = 0; i <= numOfCDs; i++)
{
while(CDList[i] == null)
i++;
CDList[i].display();
}
}
int size()
{
return numOfCDs;
}
}

if(CDList[i].getArtist().equals(artist) == true)
If you are getting NPE, here are the possibilities:
CDList is null
CDList[i] is null
CDLIst[i].getArtist() returns null
Class Artist overrides equals() and has a bug that results in NPE, but in that case the NPE would point to a statement in equals().
You haven't shown the class Artist so we can see if it overrides equals(), and haven't posted the stack trace so we can see exactly where the exception is thrown.
As others have commented, the == true is superfluous.

I would recommend using a LinkedList<CD> or ArrayList<CD> instead of CD[].
This will allow you to easily remove items, like so:
LinkedList<CD> cdList = new LinkedList<CD>();
// add items with cdList.add(...);
Iterator<CD> cdListIterator = cdList.iterator();
// Loop while the list still contains elements.
while (cdListIterator.hasNext()) {
CD thisCd = iterator.next();
// do some operation on the cd to tell whether you want to delete it
// for example:
if (thisCd.getArtist().equals(artist) && thisCd.getTitle().equals(title)) {
iterator.remove(); // it's that simple
// Don't have to mess with `cdCount--` or anything.
}
}
And, as some have commented, you don't need a.equals(b) == true; you can just use a.equals(b).

there's nothing wrong with if condition. Its your loop that has the problem.
Use a single for loop:
for(int i = 0; i <= numOfCDs; i++)
{
if(CDList[i].getArtist().equals(artist) && CDList[i].getTitle().equals(title))
{
System.out.println("Found CD: " + CDList[j].getArtist() + " " + CDList[j].getTitle());
System.out.println("Would you like to delete it? Y/1 N/0 ");
if(input.nextInt() == 1)
{
CDList[i] = null;
// do not do numOfCDs-- here
}
}
}

There are a number of problems here.
The immediate cause of your NPE is that the inner loop "removes" a CD from the list by assigning it to null, and then the outer loop tries to test the CD at the position you just removed. Since it is null, you then attempt to call null.getArtist() which NPEs.
The first thing to note is that you only need one loop. The loop body should test that the CD you are looking at has the same title AND artist ...
The next thing to note is that getting rid of the extra loop is not enough. If the delete() method is called more than once, the second call is likely to encounter a null entry that was produced by the first call ... and you will get an NPE as before. The tests should check for a null before they try to get the title / artist information; e.g.
CD cd = cdList[i];
if (cd != null &&
cd.getArtist().equals(artist) &&
cd.getTitle().equals(title)) {
// ...
}
At this point a design problem becomes apparent. These null values in the array are a bad idea. There are three fixes:
You could remove the CDs by creating a new array one element smaller ... and copy across all CDs apart from the one you are deleting.
You could add a cdListSize field, and arrange that it gives you the number of valid entries in the list. Then (and this is the important bit), when you delete an entry from the list, move the current last entry to the place where the deleted entry was and decrement the cdListSize. If you do that consistently, the null entries will all be at the end, and you can iterate from zero to cdListSize - 1 to get the non-null entries.
Best of all, use a List rather than an array to represent the CD list. The List API provides a method for removing the entry at a given position. The method really removes it ... it doesn't just set it to null.
Finally, you may need to take a step back and look at the larger application. Is the CD list supposed to be persisted; e.g. so that it is still available when your application restarts? Is it likely to be large; e.g. too large to fit into memory? Are you likely to want to do complicated queries on the CD list? All of these things would suggest that you should use a database rather than an in-memory data structure.
(However, with the extra code you've just added, it is clear that would be beyond the scope of your assignment.)

Found it! Thank ya'll for your comments, I did make some changes that ya'll recommended. The issue was with the CDList[i] being null. Just implemented a if(CDList[i] == null) then continue; Thank ya'll for your input. –

Related

How do I remove the last comma from the output in series using loop [duplicate]

So I made this to print primes between two numbers of my choice; however, it prints out a comma after the last number and I don't know how to take it off.
Example
in: 0 10
out: 2, 3, 5, 7,
I want 2,3,5,7
Scanner s = new Scanner(System.in);
int a = s.nextInt();
int b = s.nextInt();
for (int i = a; i <= b; i++){
int j;
for (j = 2; j<i; j++){
int p = i%j;
if(p==0){break;}
}
if(i == j){System.out.printf("%d,", i);}
}
}
Use a boolean to keep track of whether you've printed anything yet. Then your format string could be something like
anythingPrinted ? ",%d" : "%d"
That is, only include the comma in the format string if there's something printed.
Use a StringBuilder and write to the console at the end of your program.
StringBuilder sb = new StringBuilder();
for (int i = a; i <= b; i++){
int j;
for (j = 2; j<i; j++){
int p = i%j;
if(p==0){break;}
}
if(i == j){
// If the length of the StringBuilder is 0, no need for a comma
if(sb.length() != 0) {
sb.append(",");
}
sb.append(i);
}
}
System.out.println(sb);
This might seem like overkill, and for many cases it might be, but I have been writing a source code transcoder and I find this situation coming up a lot. Where I need commas in between values, or a prefix value which is only printed once. So I found it handy to create a class which simplifies things.
Again, you wouldn't probably want to use this if you code had one or two print loops in it, but maybe if you had more than a few. Perhaps you would remove in "on first" part if you were never going to use it.
public class FirstPrintOptions {
private PrintStream printStream;
private String onFirst;
private String remaining;
private boolean trip = false;
public FirstPrintOptions(PrintStream printStream, String onFirst, String remaining) {
this.printStream = printStream;
this.onFirst = onFirst;
this.remaining = remaining;
}
public void print() {
if (!trip) {
if (onFirst != null) {
printStream.print(onFirst);
}
trip = true;
} else {
if (remaining != null) {
printStream.print(remaining);
}
}
}
}
Then use it like this..
FirstPrintOptions firstPrintOptions = new FirstPrintOptions(System.out, null, ",");
for (int x=0;x<10;x++) {
firstPrintOptions.print();
System.out.print(x);
}
The results are..
0,1,2,3,4,5,6,7,8,9
I was testing and I came up with this. I was using compilejava.net so scanner doesn't work. I bypassed that part and just set a and b manually. Basically, it builds a string with the numbers and ends in a comma. Then it prints a substring including everything except the last comma.
import java.util.*;
public class HelloWorld {
public static void main(String[] args) {
//Scanner s = new Scanner(System.in);
int a = 2;
int b = 18;
String c = "Output = ";
for (int i = a; i <= b; i++){
int j;
for (j = 2; j<i; j++){
int p = i%j;
if(p==0){break;}
}
if(i == j){c=c+ Integer.toString(i) + ",";}
}
System.out.print(c.subSequence(0, c.length()-1));
}
}
this program for finding factors of a number
for(i=1;i<=number;i++)
{
if(number%i==0)
{
system.out.print(i);
if(i!=0)
{system.out.print(",");}
}
}
so i get the output for 10 as
1,2,5,10

Is there something wrong with my binary search algorithm?

I'm writing a program where you can enter a words which will get stored in an ArrayList. You can then search for these words, by entering them in a textField and pressing a button. (You can also sort them, if pressing another button). If the word is found the place in the ArrayList of the word should be printed out and if it's not found that should be printed out. I thought this worked until just recently when I tested it (it have worked before): I entered a word I knew was in the ArrayList which made it print out the position of the word in the ArrayList (which is what I want it to do). I then entered a word which I knew didn't exist in the ArrayList which made it print out that the word doesn't exist (which is also what I want it to do). But when I after that searched for a word I knew existed in the ArrayList, it printed out that the word couldn't be found. I then tried this with another word I knew existed in the ArrayList, but I couldn't find that either. I have after this restarted the program several times and sometimes it works and sometimes it doesn't and I have no idea why or why not...
The array gets sorted before I run the algorithm so I know that's not the problem...
Down below is the class with my search algorithm:
public class SearchAlg {
public static String binary (ArrayList<String> list, String user) {
int first = 0;
int found = 0;
int middle = 0;
int last = list.size();
String strFound = "";
while (first < last && found == 0) {
middle = ((first + last) / 2);
if (user.compareTo(list.get(middle)) > 0) {
first = middle + 1;
} else if (user.compareTo(list.get(middle)) == 0) {
found = 1;
} else if (user.compareTo(list.get(middle)) < 0) {
last = middle - 1;
}
}
if (found == 1) {
strFound = "The word " + user + " exists on the place " + middle + " in the Arraylist";
} else {
strFound = "The word " + user + " does not exist in the Arraylist";
}
return strFound;
}
}
Here is my sorting algorithm:
public class Sort {
static private String strTemp;
static private int i;
static private int n;
public static ArrayList bubbelSort (ArrayList<String> list) {
for (i = 0; i < list.size(); i++) {
for (n = 0; n < list.size() - i - 1; n++) {
if (list.get(n).compareTo(list.get(n + 1)) > 0) {
strTemp = list.get(n);
list.set(n, list.get(n + 1));
list.set(n + 1, strTemp);
}
}
}
return list;
}
And this is my Main class:
ArrayList<String> list = new ArrayList();
private void btnEnterActionPerformed(java.awt.event.ActionEvent evt) {
txtaOutput.setText("");
String wrd = txtfEnter.getText();
list.add(wrd);
for (int i = 0; i < list.size(); i++) {
txtaOutput.append(list.get(i) + "\n");
}
}
private void btnSortActionPerformed(java.awt.event.ActionEvent evt) {
txtaOutput.setText("");
Sort.bubbelSort(list);
}
private void btnSearchActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
String user = txtfSearch.getText();
txtaOutput.setText("");
String bin = SearchAlg.binary(list, user);
txtaOutput.append(bin);
}
I have no idea what's causing this, so any help is appreciated!
EDIT: I now know that the problem is that the first item in the ArrayList ins't searchable. So if the ArrayList consists of a, b, c for example, then only b and c are searchable. If I try and search for a, it says that it can't be found.
int first= 0;
int last= a.length - 1;
while (first<= last) {
int middle = first+ (last- first) / 2;
if (user.compareTo(list.get(middle)) < 0) last = middle - 1;
else if (user.compareTo(list.get(middle)) > 0) first= middle + 1;
else {
found =1 ;
break;
}
}
and don't forget to sort your list as mentioned in the previous post
The problem is in the very last step of your search. There is a chance you update the 'first' and 'last', and in the next iteration you would find the value, but instead you break from the loop.
Solution: remove the variable found entirely, and also these two lines:
} else if (user.compareTo(list.get(middle)) == 0) {
found = 1;
and where you now write...
if (found == 1) {
...instead do...
if (user.compareTo(list.get(first)) == 0) {
You're off by one.
You initialize the method with last = list.size(), implying that you're searching the half open interval [first, last> (from and including first, to but excluding last).
However, in your loop, you set last = middle - 1, which would work if your search range was the closed interval [first, last] (from and including first, to and including last).
You should make up your mind as to whether last should point on the last element, or after the last element. Here's your loop if you go with the latter:
while (first < last && found == 0) {
middle = ((first + last) / 2);
if (user.compareTo(list.get(middle)) > 0) {
first = middle + 1;
} else if (user.compareTo(list.get(middle)) == 0) {
found = 1;
} else if (user.compareTo(list.get(middle)) < 0) {
last = middle; // <-- Remove -1
}
}

How to search via character matching with a skip distance?

As the title says, I'm working on a project in which I'm searching a given text, moby dick in this case, for a key word. However instead of the word being linear, we are trying to find it via a skip distance ( instead of cat, looking for c---a---t).
I've tried multiple ways, yet can't seem to get it to actually finish one skip distance, have it not work, and call the next allowed distance (incrementing by 1 until a preset limit is reached)
The following is the current method in which this search is done, perhaps this is just something silly that I'm missing?
private int[] search()
throws IOException
{
/*
tlength is the text file length,
plength is the length of the
pattern word (cat in the original post),
text[] is a character array of the text file.
*/
int i=0, j;
int match[] = new int[2];
int skipDist = 2;
while(skipDist <= 100)
{
while(i<=tlength-(plength * skipDist))
{
j=plength-1;
while(j>=0 && pattern[j]==text[i+(j * skipDist)])j--;
if (j<0)
{
match[0] = skipDist;
match[1] = i;
return match;
}
else
{
i++;
}
}
skipDist = skipDist + 1;
}
System.out.println("There was no match!");
System.exit(0);
return match;
}
I do not know about the method you posted, but you can use this instead. I've used string and char array for this:
public boolean checkString (String s)
{
char[] check = {'c','a','t'};
int skipDistance = 2;
for(int i = 0; i< (s.length() - (skipDistance*(check.length-1))); i++)
{
boolean checkValid = true;
for(int j = 0; j<check.length; j++)
{
if(!(s.charAt(i + (j*skipDistance))==check[j]))
{
checkValid = false;
}
}
if(checkValid)
return true;
}
return false;
}
Feed the pattern to match in the char array 'check'.
String "adecrayt" evaluates true. String "cat" evaluates false.
Hope this helps.
[This part was for fixed skip distance]
+++++++++++++++++++++++++++
Now for any skip distance between 2 and 100:
public boolean checkString (String s)
{
char[] check = {'c','a','t'};
int index = 0;
int[] arr = new int[check.length];
for(int i = 0; i< (s.length()); i++)
{
if(check[index]==s.charAt(i))
{
arr[index++] = i;
}
}
boolean flag = true;
if(index==(check.length))
{
for(int i = 0; i<arr.length-1; i++)
{
int skip = arr[i+1]-arr[i];
if(!((skip>2)&&(skip<100)))
{
flag = false;
}
else
{
System.out.println("Skip Distance : "+skip);
}
}
}
else
{
flag = false;
}
return flag;
}
If you pass in a String, you only need one line:
public static String search(String s, int skipDist) {
return s.replaceAll(".*(c.{2," + skipDist + "}a.{2," + skipDist + "}t)?.*", "$1");
}
If no match found, a blank will be returned.

Java code with tests - infinite loop?

I try to get the relationship between people. However, when I run unit test, the test runs forever, it doesn't get the result and my CPU usage was high.
Could someone see what's wrong with my code?
The string relations are multiple line inputs of string with in the format of "A , B C , D" where A is the parent of B and C is the parent of D.
This is the default constructor for the code and the input in string format. We don't need to check if the format is correct:
public SeeRelations(String relations){
this.relations = relations;
}
This the helper function to get each line of the string from the formatted input:
//helper function to get each line of the string
private ArrayList<String> lineRelations(){
int i;
ArrayList<String> lineRelations = new ArrayList<String>();
String[] lines = relations.split("\n");
for(i = 0; i < lines.length; i++){
lineRelations.add(lines[i]);
}
return lineRelations;
}
This is the function to put all the relations from the input formatted string to arraylists:
//helper function to put each of the relationship in arraylists
private ArrayList<ArrayList<String>> allRelations(){
int i;
ArrayList<ArrayList<String>> allRelations = new ArrayList<ArrayList<String>>();
ArrayList<String> lineRelations = lineRelations();
for(i = 0; i < lineRelations.size(); i++){
ArrayList<String> eachLine = new ArrayList<String>(Arrays.asList(lineRelations.get(i).split("\\s*,\\s*")));
allRelations.add(eachLine);
}
return allRelations;
}
This is the method to check if the input name exists:
//helper function to see if the name exist for seeRelations()
private boolean hasThisName(String name){
ArrayList<ArrayList<String>> allRelations = allRelations();
int i;
int j;
for(i = 0; i < allRelations.size(); i++){
for(j = 0; j < allRelations.get(i).size(); j++){
if(name.equals(allRelations.get(i).get(j))){
return true;
}
}
}
return false;
}
This is the function to get the generation number between two people:
//helper function to get Generation number of seeRelations()
private int getGenerationNum(String person, String ancestor){
ArrayList<ArrayList<String>> allRelations = allRelations();
String name;
int i;
int j;
int generationNum = 0;
for(i = 0, j = 0, name = ancestor; i < allRelations.size(); i++){
if(name.equals(allRelations.get(i).get(0)) && !person.equals(allRelations.get(i).get(1))){
generationNum++;
ancestor = allRelations.get(i).get(1);
i = 0;
j = 1;
}
else if(ancestor.equals(allRelations.get(i).get(0)) && person.equals(allRelations.get(i).get(1))){
generationNum++;
j = 1;
break;
}
}
if(j == 0){
return 0;
}
else{
return generationNum;
}
}
This is the method to get multiple of "great" for the final output:
private String great(int num){
int i;
String great = "";
for(i = 0; i < num; i++){
great += "great";
}
return great;
}
This is my final method to check the relationship between two people:
public String SeeRelations(String person, String ancestor){
int generationNum = getGenerationNum(person, ancestor);
String great = great(generationNum - 2);
if(!(hasThisName(person) && hasThisName(ancestor))){
return null;
}
else{
if(generationNum == 0){
return null;
}
else if(generationNum == 1){
return ancestor + " is the parent of " + person;
}
else if(generationNum == 2){
return ancestor + " is the grandparent of " + person;
}
else{
return ancestor + " is the" + " " + great +"grandparent of " + person;
}
}
}
This is my test cases, And it runs forever and couldn't get a result
public class FamilyTreeTest {
#Test
public void testSeeRelations() {
FamilyTree relation2 = new FamilyTree("John Doe , Mary Smith" + "\n" + "Martin Weasel , John Doe");
assertEquals("Martin Weasel is the grandparent of Mary Smith", familyTree2.SeeRelations("Mary Smith", "Martin Weasel"));
}
for(i = 0, j = 0, name = ancestor; i < allRelations.size(); i++){
if(name.equals(allRelations.get(i).get(0)) && !person.equals(allRelations.get(i).get(1))){
generationNum++;
ancestor = allRelations.get(i).get(1);
i = 0;
j = 1;
}
else if(ancestor.equals(allRelations.get(i).get(0)) && person.equals(allRelations.get(i).get(1))){
generationNum++;
j = 1;
break;
}
}
here you have your faulty lines
in your case your ancestor/name is "Martin Weasel" given relation for martin is "John Doe", but you are looking for mary smith so name.equals(allRelations.get(i).get(0)) && !person.equals(allRelations.get(i).get(1))) this is true and this i = 0; makes your loop starts from beginning
what you could do, try to create object person
ie
class Person{
String name;
List childrens;
List parents;
...
}
then just do simple tree walker
int SearchDown(Person person, String searchedRelation,int generation)
{
if person.getName().equals(searchedRelation())
return generation;
for (Person child: person.getChildren())
{
int generation = SearchDown(child, searchedRelation, generation+1);
if (generation!=-1) return generation;
}
return -1;
}
etc...
i'm really finding this way much easier to deal with all types of trees

I am unable to display the path taken inside my maze from start to finish

I am reading the maze outline in from an input file and storing the values in a 2D array. I am able to find the exit in my findPath() method, but i am unsure how to trace the actual path from start to finish.
I want to change the char value in the "Room" to a '.' if it is on the actual path. Please advise how i can accomplish this. Any help is greatly appreciated. Thanks.
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.PrintWriter;
import java.util.*;
import javax.swing.JOptionPane;
public class Maze {
String inFile, // Name of file to be used as input
outFile, // Name of file to output completed maze to
line; // Current line being read by scanner
Room [][] rooms; // Holds the values that create maze
Room [] theStack;
Room goal;
Room current = new Room();
int rows, columns;
int tos = 0;
char [][] mazeC;
public static void main(String []args) throws Exception {
Maze m = new Maze();
}
public Maze() throws FileNotFoundException {
// Prompts user for the name of the file they wish to use as the input file.
inFile = JOptionPane.showInputDialog(null, "Please enter the name of the file you wish to read, including " + "the file path:");
if(inFile.equals("")) inFile = "C:/java/javaFiles/maze1.txt";
// Prompts user to enter the name they wish to save the file under.
outFile = JOptionPane.showInputDialog(null, "Please enter the filename you wish to save the data to:");
if(outFile.equals("")) outFile = "C:/java/javaFiles/mazeoutput1.txt";
// Creates a scanner object to read in the input file.
Scanner readFile = new Scanner(new FileReader(inFile));
PrintWriter output = new PrintWriter(outFile);
rows = readFile.nextInt();
columns = readFile.nextInt();
readFile.nextLine();
theStack = new Room[1000];
rooms = new Room [rows][columns];
for(int i = 0; i < rows; i++) {
line = readFile.nextLine();
for(int j = 0; j< line.length(); j++) {
Room r = new Room();
r.setValue(line.charAt(j));
if(r.getValue() == '$')
r.setGoal(true);
r.setBlocked(false);
if (r.getValue() == '*') {
r.setBlocked(true);
r.setGoal(false);
} else {
r.setGoal(false);
r.setBlocked(false);
}
r.setCord(i, j);
rooms[i][j] = r;
//mazeContent[i][j] = line.charAt(j);
}
}
createRooms();
findPath();
for(int i = 0; i < rows ; i++) {
for(int j = 0; j < columns ; j++) {
System.out.print(rooms[i][j].getValue());
}
System.out.println();
}
}
public void createRooms() {
for(int i = 1; i < rows - 1; i++) {
for(int j = 1; j < columns -1; j++) {
rooms[i][j].setCord(i,j);
rooms[i][j].setValue(rooms[i][j].getValue());
rooms[i][j].setUp(rooms, i, j);
rooms[i][j].setDown(rooms, i, j);
rooms[i][j].setRight(rooms, i, j);
rooms[i][j].setLeft(rooms, i, j);
if(rooms[i][j].getValue() == '*')
rooms[i][j].setBlocked(true);
else
rooms[i][j].setBlocked(false);
//System.out.println(rooms[i][j].getValue());
}
}
}
public void findPath() {
for(int i = 0; i < rows ; i++) {
for(int j = 0; j < columns ; j++) {
System.out.print(rooms[i][j].getValue());
}
System.out.println();
}
Room start = rooms[1][1];
push(start);
while(!isEmpty()) {
current = pop();
System.out.println("The value stored in current is" + current.getValue()+ "");
if (current == null)
System.out.println("current is null");
else if(current.getValue() == '$') {
System.out.println("Success");
current.setValue('f');
/*for (int i = 0; i < tos; i++) {
}*/
}
//System.out.println("The value is " + current.getValue());
else if(current.getBlocked() == false && current.getVisited() == false) {
System.out.println("pushing currents neighbors left, right....etc" +
"current is at" + current.getCord());
current.setVisited(true);
//
if(current.getRight() != null){
push(current.getRight()); System.out.println("Inside push 1" +current.getRight().getCord());}
else System.out.println("Inside push right is null");
if(current.getLeft() != null){
push(current.getLeft()); System.out.println("Inside push 2 " + current.getLeft().getCord());}
else System.out.println("Inside push left is null");
if(current.getUp() != null) {
push(current.getUp()); System.out.println("Inside push 3" + current.getUp().getCord());}
else System.out.println("Inside push up is null");
if(current.getDown() != null) {
push(current.getDown()); System.out.println("inside push 4" + current.getDown().getCord());}
else System.out.println("Inside push down is null");
}
}
}
public Room pop() {
// TODO Auto-generated method stub
System.out.println("I have Popped");
return theStack[--tos];
}
public boolean isEmpty() {
// TODO Auto-generated method stub
return tos == 0;
}
public void push(Room item) {
System.out.println("I have pushed");
if (isFull()) {
System.out.println("The stack is full!");
}
else if(item == null){
System.out.println("you are pushing a null object");
}
else
System.out.println("stuff added");
theStack[tos++] = item;
}
public boolean isFull() {
return tos == theStack.length-1;
}
}
I haven't really gone through your code line by line but here's a solution: (I wrote a similar program for finding Djikstra's shortest path in a graph)
Make an attribute called PREVIOUS in your room object.
Every time you go to a 'next room', make sure you change your next room's PREVIOUS attribute to the room you came from.
When you reach your destination: Start with your destination's PREVIOUS and traverse back through the rooms until you hit a room with no PREVIOUS, which will be your source (start) room. i.e. go to the PREVIOUS room, add it to the stack, go to its PREVIOUS and repeat the process until you hit your starting room.
This should work because: If you go through a path of rooms and you hit a dead-end you will back track and start going through a new path. Eventually you will recursively over-write the PREVIOUS attribute for each room in your new path (every time). When you hit your destination, you will have the most updated (correct) PREVIOUS attribute in every room in your current (correct) path. So traverse back and add the PREVIOUS of each room to a stack or a queue or (whatever you want) as you go. This should give you your path.

Categories

Resources