I have to write a program for a Boggle-like game, and I currently have it check each letter below the current one to see if they make a word. So for a board like so:
W O Y R
F U M F
H T R V
I G S W
The only word it would find is "OUT" going from top to bottom. When it finds part of a word it puts that letter into a string and sets it to null so it won't use a letter twice in the same word (the full algorithm has to be able to search in multiple directions). I use a stack to keep track of the coordinates of the letters I've used so I can backtrack, and every time I pop the stack I take the last letter of the string and put it back into the board in its original position. But the issue is that if multiple letters are removed, it places them all in the same index, overwriting the previous one. So in the case of "OUT" the board ends up looking like this after replacing the three letters:
W null Y R
F null M F
H O R V
I G S W
I've gone through my code and tried rewriting it twice but it always does this. Do you have any insight as to why this is happening?
private void checkNeighbors(LetterCoor center){
String check = out;
while (!path.empty()){
if(center.getDirec()==0){//If the direction to check is down
System.out.println("Bottom");
if((center.getRow())+1<sideLength && board[(center.getRow())+1][center.getCol()]!=null){//makes sure the space below is !null and !out of bounds
check+=board[center.getRow()+1][center.getCol()];
System.out.println("Checking " + check);
if(isValidWord(check)){//checks if string is part of the lexicon
center.nextNeighbor();
board[center.getRow()+1][center.getCol()]=null;
center = new LetterCoor(center.getRow()+1, center.getCol(), 0);
System.out.println("push " + check.substring(check.length()-1));
path.push(center);
out=check;
}
else{
center=(LetterCoor) path.pop();
center.nextNeighbor();
path.push(center);
}
}//end of null if
else{
System.out.println("Null or end of board");
center=(LetterCoor) path.pop();
center.nextNeighbor();
path.push(center);
}
}//end of direc 0 if
else{
System.out.println("pop " + out.substring(out.length()-1,out.length()));
center=(LetterCoor) path.pop();
center.nextNeighbor();
board[center.getRow()][center.getCol()]=out.substring(out.length()-1,out.length());
out=out.substring(0,out.length()-1);
if (center.getDirec()<1){
path.push(center);
}
}
System.out.println("Current string is " + out);
}//end of while loop
}
If you need any clarification of my code please let me know.
Also, as clarification the LeterCoor object stores three ints. The first is the row index of the letter, the second is the column index and the third indicates which direction it is searching in (0=down, 1=down right, 2=right, etc)
I ended up coming across the solution on my own. The issue was with my LetterCoor object. Eclipse required the variables be set as static since I had the object class in a separate file, so when I updated the coordinate data in one LetterCoor object, it set the data for every LetterCoor object to that coordinate. I resolved this by moving the object class into the same file as this class and removing the static declaration from the variables.
Related
I'm trying to print each step of a Tower of Hanoi using an array of objects. The objects I'm using are Pokemon objects with only a name. It does have other attributes that are irrelevant to this code. I'm using only the names to sort the Tower. The Array of Pokemon objects is sorted by alphabetical order using this code below:
for ( int i = 0; i<pokemon.length;i++){
for ( int j = i+1; j<pokemon.length; j++){
if ( (pokemon[j].getName().compareTo(pokemon[i].getName())<0)){
String temp = pokemon[i].getName();
pokemon[i].setName(pokemon[j].getName());
pokemon[j].setName(temp);
}
}
}
After the array is properly sorted, I then created this print method to display the Tower of Hanoi process happening.
static public void printArray(int n, Pokemon[] a, Pokemon[] b, Pokemon[] c) {
String slot1 = "";
String slot2 = "";
String slot3 = "";
System.out.println("A\t\tB\t\tC");
for (int i = 0; i < n; i++) {
if (!a[i].getName().equals("")) {
slot1 = a[i].getName();
if (!b[i].getName().equals("")) {
slot2 = b[i].getName();
if (!c[i].getName().equals("")) {
slot3 = c[i].getName();
} else
slot3 = "";
} else
slot2 = "";
} else
slot1 = "";
System.out.println(slot1 + "\t\t" + slot2 + "\t\t" + slot3);
}
}
I understand that using \t to format is a poor choice, but for debugging purposes this is functional for now, I hope to convert it to printf for a better format. The purpose of this printArray method is to print the A B C array's from a top down view.
For every element in the array that does not have a name, i.e. it was never set to anything, it does not print it. This way it only prints the 'action' that is happening. I've verified this by using setName with both random Strings and empty Strings("") to see if it printed correctly, it does.
Next I decided to take a stab at the actual recursion method itself and ended up with this mess
static public void Hanoi(int n, Pokemon[] a, Pokemon[] b, Pokemon[] c){
int a1 =n;
int b1 =n-1;
int c1 =n-1;
for ( int i = 0; i < n;i++){
if ( !a[i].getName().equals("")){
a1--;
}
if ( !b[i].getName().equals("")){
b1--;
}
if ( !c[i].getName().equals("")){
c1--;
}
}
if ( n > 0 ){
printArray(n, a, b,c);
Hanoi(n-1, a, c, b);
c[c1].setName(a[a1].getName());CC
a[a1].setName("");
Hanoi(n-1,b, a, c);
System.out.println("\n\n\n");
}
}
N is the number the user enters ( 'Numbers of disks' )
I should also comment this but I tend to want to make sure my program works before commenting and having everything get messy. The point of the if statements is to decrement the index counters for each individual array (A,B,C) if there is a name already in the array. The higher the index means the bottom of the stack, literally.
I'm fairly lost now and have no idea what to be checking but I'm doing what I can with little bugtests but if anyone has had experience with this and give me some advice or point something out, I would appreciate it!
Note: I'm a student studying OOP right now so my tools are limited to what we have already learned, therefore I'm trying to do this with what I already know, Arrays to handle the Tower of Hanoi Recursive Method.
EDIT: Sorry, it was late at night and I was extremely tired and not thinking clearly to post a logical question. The issue I'm having is tracing back my logic. I get confused when I get to the recursive function calls.
If I enter a 3, the most simple of Tower of Hanoi problems, then I get this sample output
3
A B C
Bulbasaur
Pikachu
Squirtle
A B C
Bulbasaur
Pikachu
A B C
Bulbasaur
The method call is
Hanoi(3,pokemon,b,c)
Tracing back the logic I end up with a1 = 0, b1, = 2, and c1 = 2, which corresponds with the first print for all the indexes
A B C
Bulbasaur
Pikachu
Squirtle
This is where I get confused , when I call the Hanoi(n-1,a,c,b) does the code end up printing 2 times before the outermost loop is finished? If so, I can't decide where to put the print statement because I need the output to only print once every time something changes.
For the regular Tower of Hanoi I think I understand the print line
System.out.println("Moving a stack from", A, C)
However when dealing with Arrays I need to set a value somewhere into the C array and remove a value from the A array, effectively causing a "move", which I have in the lines
c[c1].setName(a[a1].getName());
a[a1].setName("");
If this logic happens after the recursive function call, does that mean that it resolves the innermost loop first? So when n = 1? At this point I'm completely lost because I know that calling the recursive function with
Hanoi(n-1,a,c,b)
means that everytime it does the destination and auxilary array are being switched around, I can't wrap my head around this. Where do I use the print statements. How does the recursive function calls affect my shifting of the disks, is there a better way to deal with Tower of Hanoi with Arrays then using individual indexes to keep track of each Array, because it seems to not work after the Arrays are switched from their original position.
I've developed an android Travelling Salesman Problem (TSP) game application in which the user makes a path and plays against the computer, which uses the TSP algorithm to make a full path every time the user clicks to join two points with a line. Currently my method for the computer's path being draw is called whenever the user makes their move. However, my code is only allowing the first two points in the computer's path (stored in the arraylist called 'test') to be joined up.
public void CompDrawLine(List<Point> test) {
int d = 0;
int i;
test.add(test.get(0));
Point c = test.get(d);
for (i=0;i<test.size();i++)
{
cPath.moveTo(c.x,c.y);
c = test.get(d+1);
cPath.lineTo(c.x,c.y);
mCanvas.drawPath(cPath,cPaint);
// String testIndex = "this is iteration" + i;
// Toast.makeText(mContext, testIndex, LENGTH_SHORT).show();
}
cPath.reset();
}
How do I get the complete path drawn whenever the method is called??
I think your error is in the second line of your for loop. The variable d is never being incremented, so you are always using points 0 and 1. Personally, I would get rid of the d variable and just use i like this:
c = test.get(i+1);
However, another option would be to use d and increment it each time:
c = test.get(++d);
It must be a pre-increment though, or else you will be going from point 0 to point 0, and then point 1 to point 1, etc. instead of point 0 to 1, since d is initialized to 0.
here are my requirements:
Create (hard coded) the 50 states and their capital cities, using a 2
dimension array.
In the dialog box: ask the user either to enter the State or a City.
If the state is entered, find its capital city. If a city is entered,
find its State.
If not, found, issue an error message.
This should be in a Loop, until the user does not want to play
anymore.
I really don't know where to start, all I have done so far is create the array, I don't really get how to search the array, and spit out the corresponding state/capital.
Any help would be greatly appreciated.
Here is the code I have written so far.
import java.util.Scanner;
public class GuessStates {
public static void main(String[] args){
java.util.Scanner input = new java.util.Scanner(System.in);
String[][] statesAndCapitols = {
{"Alabama","Alaska","Arizona","Arkansas","California","Colorado","Connecticut","Delaware","Florida","Georgia","Hawaii","Idaho","Illinois","Indiana","Iowa","Kansas","Kentucky","Louisiana","Maine","Maryland","Massachusetts","Michigan","Minnesota","Mississippi","Missouri","Montana","Nebraska","Nevada","New Hampshire","New Jersey","New Mexico","New York","North Carolina","North Dakota","Ohio","Oklahoma","Oregon","Pennsylvania","Rhode Island","South Carolina","South Dakota","Tennessee","Texas","Utah","Vermont","Virginia","Washington","West Virginia","Wisconsin","Wyoming"},
{"Montgomery","Juneau","Phoenix","Little Rock","Sacramento","Denver","Hartford","Dover","Tallahassee","Atlanta","Honolulu","Boise","Springfield","Indianapolis","Des Moines","Topeka","Frankfort","Baton Rouge","Augusta","Annapolis","Boston","Lansing","St. Paul","Jackson","Jefferson City","Helena","Lincoln","Carson City","Concord","Trenton","Santa Fe","Albany","Raleigh","Bismarck","Columbus","Oklahoma City","Salem","Harrisburg","Providence","Columbia","Pierre","Nashville","Austin","Salt Lake City","Montpelier","Richmond","Olympia","Charleston","Madison","Cheyenne"}};
System.out.println("Please enter a State or a capitol city.");
String userInput = input.nextLine();
}
}
thanks again!
try searching through the array with a for loop.
Using a for loop it keeps track and updates your current position of traversing the array.
Once you find the correct state or capital (by checking if userInput.equalsIgnoreCase(statesAndCapitols[x][y]), then take the current position you are at and retrieve the information needed.
I.E.
for(int x = 0; x < 2; ++x) //loop through states the first time, capitols the second
for(int y = 0; y < 50; ++y) //always 50, unless new states get added (obviously not a problem in this example, but useful to think about in future problems - YOUR DATA WILL ALMOST ALWAYS CHANGE.
if(userInput.equalsIgnoreCase(statesAndCapitols[x][y])
System.out.println(statesAndCapitols[x == 1 ? 0 : 1][y]);
In the array, I did x == 1 ? 0 : 1. That's a ternary operator, what it's saying is if x is equal to 1, use the value 0, otherwise use the value 1.
That's one way to go about this problem.
Another way would be to create your own Class/Datatype for the cities and states, that way you don't need to keep your arrays in sync, meaning you don't need to update 2 items for one change (like add another city/state combo).
Hope this helps a bit! :)
String entered_state=input.nextLine();
for(int i=0;i<50;i++){
if(statesAndCapitols[0][i].equals(entered_state)){
String searched_city=statesAndCapitols[1][i];
//print the city name
break;
}
}
if(i==50)
//print error
Same thing for searching state from entered city.
Here is the algorithm (not working) Please let me know where the error is
Thanks
private void checkSouth(Location point, int player) {
//Loop through everything south
boolean isthereAnOppositePlayer=false;
int oppositePlayer=0;
//Set opposite player
if (player==1) {
oppositePlayer=2;
}else{
oppositePlayer=1;
}
for (int i = point.getVertical(); i < 8; i++) {
//Create a location point with the current location being compared
MyLocation locationBeingChecked= new MyLocation();
locationBeingChecked.setHorizontal(point.getHorizontal());
locationBeingChecked.setVertical(i);
int value = board[locationBeingChecked.getVertical()][locationBeingChecked.getHorizontal()];
//If the first checked is the opposite player
if (value==oppositePlayer) {
//Then potential to evaluate more
isthereAnOppositePlayer=true;
}
//If it isn't an opposite player, then break
if(!isthereAnOppositePlayer && value!=0){
break;
}
//If another of the player's piece found or 0, then end
if (isthereAnOppositePlayer && value==player || isthereAnOppositePlayer && value==0) {
break;
//end
}
//Add to number of players to flip
if(isthereAnOppositePlayer && value==oppositePlayer && value!=0){
//add to array
addToPiecesToTurn(locationBeingChecked);
}
}
}
It looks like the locations that got rotated back to the other player are the exact same as those rotated during the first move. I would guess that the array being populated by addToPiecesToTurn is perhaps not being cleared out between each move, so all the previous locations are still in there.
If you are storing the pieces to be turned in an ArrayList, you can use the clear() method to erase the contents of the collection between each turn.
Another possible problem is that you are checking for the opposite player, and then instantly beginning to populate addToPiecesToTurn. However, the pieces in that direction are not necessarily valid to be rotated unless they are "sandwiched" in by a second location containing the current player's piece. I don't think your code is properly checking for that case; when that happens, you'll want to somehow skip flipping those pieces to the other player, such as clearing out the array of piecesToTurn.
Edit: Looking at your current solution where you are implementing every direction separately, you are going to have a lot of duplicated code. If you think about what it means to walk along a certain direction, you can think of it as adjusting the x/y value by a "step" amount. The step amount could be -1 for backwards, 0 for no move, or 1 for forwards. Then you could create a single method that handles all directions without duplicating the logic:
private void checkDirection(Location point, int player, int yStep, int xStep) {
int x = point.getHorizontal() + xStep;
int y = point.getVertical() + yStep;
MyLocation locationBeingChecked = new MyLocation();
locationBeingChecked.setHorizontal(x);
locationBeingChecked.setVertical(y);
while (isValid(locationBeingChecked)) {
// do the logic here
x += xStep;
y += yStep;
locationBeingChecked = new MyLocation();
locationBeingChecked.setHorizontal(x);
locationBeingChecked.setVertical(y);
}
}
You would need to implement isValid to check that the location is valid, i.e., in the board. Then you could call this method for each direction:
// north
checkDirection(curPoint, curPlayer, -1, 0);
// north-east
checkDirection(curPoint, curPlayer, -1, 1);
// east
checkDirection(curPoint, curPlayer, 0, 1);
// etc
This is the sort of problem that is ripe for some unit testing. You could very easily set up a board, play a move, and validate the answer, and the test results would give plenty of insight into where your expectations and reality diverge.
why didn't you use a 2d array ?
each cell would contain an enum : EMPTY, PLAYER_1, PLAYER_2 .
then, in order to go over the cells, you simply use loops for each direction.
for example, upon clicking on a cell , checking to the right would be:
for(int x=pressedLocation.x+1;x<cells[pressedLocation.y].length;++x)
{
Cell cell=cells[pressedLocation.y][x];
if(cell==EMPTY||cell==currentPlayerCell)
break;
cells[pressedLocation.y][x]=currentPlayerCell;
}
checking from top to bottom would be:
for(int y=pressedLocation.y+1;y<cells.length;++y)
{
Cell cell=cells[y][pressedLocation.x];
if(cell==EMPTY||cell==currentPlayerCell)
break;
cells[y][pressedLocation.x]=currentPlayerCell;
}
I have a problem on a program I'm making that I honestly can't find a solution for. It seems the objects contained on a Java ArrayList collection are being modified without me programming such modifications.
The program as a whole is meant to basically create a random connection between two nodes on a 10x10 grid by moving through a path. This path is represented as an ArrayList collection of points in the grid, with the first index containing the first node's location (node A) and the last index containing the second node's location (node B). How I do this is by locating myself on A's location, and then moving randomly to contiguous points in the grid, repeating this in a while loop until B's location is reached.
Everything seems to work except that the "path" collection is altered somehow, such that every point in it ends up being the same as the last point to which I move, which is also B's location.
The method is as follows:
public void generateRandomPath()
{
path = new ArrayList<Point>();
path.add(pInitial);
complete = false;
while(!complete)
{
k = path.get(path.size()-1);
d = selectDirection(k);
GUI.log.append("==== Before the method. ==== \n");
GUI.log.append(Integer.toString(path.get(path.size()-1).getX())+" - "+Integer.toString(path.get(path.size()-1).getY())+"\n");
x = move(k, d);
path.add(x);
if(k.getX() == pEnd.getX() && k.getY() == pEnd.getY())
complete = true;
}
GUI.log.append("Finished. \n");
}
"Point" are simply points, with an X
and Y coordinate represented by
integers.
"pInitial" is the point representing the location of node A.
"pEnd" is the point representing the location of node B.
"d" is the direction on which I'm going to move on this repetition. This can be either up, right, down, or left represented by an integer 1, 2, 3, and 4 respectively.
"k" is the last point in the path, which is the point to which it moved on the previous repetition.
"x" is the new point to which it moved on the current repetition.
So what it basically does is it grabs the last point in the path as reference, chooses a direction, and then moves to the point contiguous on that direction. Each repetition of the while loop should add a new point to path. However what ends up happening is that not only is this new point added, but every other point already in path takes the value of this last point added. By utilizing the log entries show above (GUI.log.append) I managed to see that path is being mysteriously altered inside the step:
x = move(k, d);
Which is the following method:
private Point move(Point n, int y)
{
GUI.log.append("==== Inside the method. ==== \n");
GUI.log.append(Integer.toString(path.get(path.size()-1).getX())+" - "+Integer.toString(path.get(path.size()-1).getY())+"\n");
Point newP = n;
if(y == 1)
newP.setY(n.getY()-1);
if(y == 2)
newP.setX(n.getX()+1);
if(y == 3)
newP.setY(n.getY()+1);
if(y == 4)
newP.setX(n.getX()-1);
GUI.log.append("==== After method. ==== \n");
GUI.log.append(Integer.toString(path.get(path.size()-1).getX())+" - "+Integer.toString(path.get(path.size()-1).getY())+"\n");
return newP;
}
Integer y is the direction as mentioned before. As you can see this method does not alter path in any way, yet the logs show it does. In this example node A was on the point X = 2, Y = 3. The log shows what the coordinates of the last point in path are. As you can see, the coordinates of the last point in path take on the value of the coordinates of the new point, but this new point was not yet added to path.
I honestly don't know how this is happening. If anyone could think of a reason I would appreciate it very much if you could tell me.
Try
Point newP = new Point(n.getX(), n.getY());
instead of
Point newP = n;