Printing the shortest path with BFS - java

I am creating a maze solver which uses Breadth First Search algorithm and I'm wondering if I can somehow print the path on the grid instead of just printing the distance value it travelled in order to find the exit. Here is the code down below and thanks in advance.
public List<Coords> solve(int x, int y) {
Queue<Coords> q = new LinkedList<>();
List<Coords> visited = new ArrayList<>();
Coords start = new Coords(x,y);
q.add(start);
visited.add(start);
while(!q.isEmpty()) {
Coords get = q.poll();
if(maze[get.x][get.y] == 3) {
System.out.println("found an exit!");
System.out.println("Distance: " + get.dist);
break;
}
if(!visited.contains(get)) {
visited.add(get);
}
if(isValid(get.x-1, get.y)) {
q.add(new Coords(get.x-1, get.y, get.dist+1));
}
if(isValid(get.x, get.y-1)) {
q.add(new Coords(get.x, get.y-1, get.dist+1));
}
if(isValid(get.x+1, get.y)) {
q.add(new Coords(get.x+1, get.y, get.dist+1));
}
if(isValid(get.x, get.y+1)) {
q.add(new Coords(get.x, get.y+1, get.dist+1));
}
}
return visited;
}
}
The output is :
found an exit! Distance: 20

I'm not sure I understand the question perfectly, but don't you already have this data in your Queue<Coords> q object?
If that's the case, then you could have something like this:
if (maze[get.x][get.y] == 3) {
System.out.println("found an exit!");
System.out.println("Distance: " + get.dist);
for(Coords c : q) {
System.out.println(c);
}
break;
}

Related

Need feedback on my Breadth First Search algorithm between two strings

I am attempting to find the shortest path in a route between two points. My adjacency list seems to be correct but the breadth-first search seems to be messing up somewhere. If no path exists between two points in the graph, "Not found" is printed. My code never seems to enter this for some reason, even if it should. My basic understanding of the BST algorithm is making this problem extremely hard to diagnose. I've spent countless hours modifying the code and watching videos but have remained unsuccessful.
I am reading the route data from a text. This part is working perfectly, therefore I feel like it would be redundant to include. What I will say is that the adjacency list my graph code creates looks correct, so it's likely an issue with my BFS function.
class Graph {
// We use Hashmap to store the edges in the graph
private Map<String, List<String> > map = new HashMap<>();
public void BFS(String start, String stop) {
Queue<String> queue = new ArrayDeque<>();
HashSet<String> seen = new HashSet<>();
ArrayList<String> network = new ArrayList<>();
queue.add(start);
while(0 != queue.size()){
String vertex = queue.poll();
if(!seen.contains(vertex)){
network.add(vertex);
queue.addAll(map.get(vertex)); // Add all neighbors of 'vertex' to the queue
seen.add(vertex);
}
}
if (network.contains(stop)) {
System.out.println("Route Path: ");
for(String location: network) {
if (location.equals(stop)) {
System.out.println(location);
break;
} else {
System.out.println(location + " -> ");
}
}
} else {
System.out.println("Not found.");
}
}
public void printMap() {
for(String item: map.keySet()) {
System.out.println(map.get(item));
}
}
// This function adds a new vertex to the graph
public void addVertex(String s)
{
map.put(s, new LinkedList<String>());
}
// This function adds the edge
// between source to destination
public void addEdge(String source,
String destination,
boolean bidirectional)
{
if (!map.containsKey(source))
addVertex(source);
if (!map.containsKey(destination))
addVertex(destination);
map.get(source).add(destination);
if (bidirectional == true) {
map.get(destination).add(source);
}
}
// This function gives the count of vertices
public void getVertexCount()
{
System.out.println("The graph has "
+ map.keySet().size()
+ " vertex");
}
// This function gives the count of edges
public void getEdgesCount(boolean bidirection)
{
int count = 0;
for (String v : map.keySet()) {
count += map.get(v).size();
}
if (bidirection == true) {
count = count / 2;
}
System.out.println("The graph has "
+ count
+ " edges.");
}
// This function gives whether
// a vertex is present or not.
public boolean hasVertex(String s)
{
if (map.containsKey(s)) {
return true;
}
else {
return false;
}
}
// This function gives whether an edge is present or not.
public boolean hasEdge(String s, String d)
{
if (map.get(s).contains(d)) {
return true;
}
else {
return false;
}
}
// Prints the adjancency list of each vertex.
#Override
public String toString()
{
StringBuilder builder = new StringBuilder();
for (String v : map.keySet()) {
builder.append(v.toString() + ": ");
for (String w : map.get(v)) {
builder.append(w.toString() + " ");
}
builder.append("\n");
}
return (builder.toString());
}
If my question is lacking in any way, please provide constructive feedback so I can make better posts in the future. I can refine my post and supply further information if needed.

Why does my for loop which calls the addLink method not print the proper coefficient and exponent values?

The first for loop prints the proper coeffcient and exponent values as
provided by the value string, but the second for loop which class the
addLink method does not print the proper values? I cannot see what the
problem is. Why does the output from the first for loop not match the output from the second?
The code has been edited. I have moved the addLink method into the first for loop and my output is shown below. it is still not what I am intending.
public class Polyvalues {
Term head;
public Polyvalues() {
String value = "5 6 8 9 1 9";
String sub[] = value.split(" ");
double coeff = 0;
int exp = 0;
for (int i = 0; i < sub.length; i++)
{
if (sub[i].isEmpty()) {
System.out.println("No input");
}
if (i % 2 == 0) {
try {
coeff = Double.parseDouble(sub[i]);
System.out.println("Coeff is " + coeff);
} catch (NumberFormatException e) {
System.out.println("Fix This");
}
} else {
try {
exp = Integer.parseInt(sub[i]);
System.out.println("The exp is " + exp);
} catch (NumberFormatException e) {
System.out.println("Fix This");
}
}
this.addLink(coeff, exp);//moved from commented out for-loop
}
System.out.println("*******************************************");
/*for (int i = 0; i < sub.length; i++)
{
this.addLink(coeff, exp);
}*/
}//end constructor
public void addLink(double a, int b)
{
if(head == null)
{
head = new Term(a,b);
return;
}
Term currNode = head;
while(currNode.next != null)
{
currNode = currNode.next;
}
currNode.next = new Term(a,b);
//addLink(a,b);
}
static class Term{
double coeff;
int exp;
Term next;
Term(double c, int e){
this.coeff = c;
this.exp = e;
this.next = null;
System.out.println("The Coeff "+ this.coeff);
System.out.println("The Exp "+ this.exp);
}
}
public static void main(String[] args)
{
Polyvalues p1 = new Polyvalues();
}
} //end of class
Now, I get this when I move the addLink method into the first for-loop. Why am I getting these duplicate outputs when I print?
When this is what I want:
Is it my nodes?
Because in the second loop you are passing the same value of coeff and exp every time.
At the end of your first loop value of coeff is 1.0 and exp is 9
and you are passing that same value every time, in the second loop, to method addLink.
To solve it either make an array to store every value or just call addLink in the first loop.
You really need to learn how to debug your code. Every programmer needs to know how to debug code. Have you read this Web page? How to debug small programs
In any case, if you are using an IDE (like Eclipse or IntelliJ) then it should have a debugger and you should learn to use it.
You are close with your code. You just need to move the call to method addLink. (See the below code.) If you step through the code using a debugger, you will understand why. Basically you need to call addLink after you have obtained a value for both coeff and exp. In your code you are calling addLink twice – once when you only have the coeff value and the second time when you have both coeff and exp.
In the below code, I have indicated the change with the comment Moved from after this 'else' block. I also left the original line but commented it out.
Also note that I added [overridden] toString methods just to make it easier to see the results of executing the code.
public class Polyvalues {
Term head;
public Polyvalues() {
String value = "5 6 8 9 1 9";
String sub[] = value.split(" ");
double coeff = 0;
int exp = 0;
for (int i = 0; i < sub.length; i++) {
if (sub[i].isEmpty()) {
System.out.println("No input");
}
if (i % 2 == 0) {
try {
coeff = Double.parseDouble(sub[i]);
System.out.println("Coeff is " + coeff);
}
catch (NumberFormatException e) {
System.out.println("Fix This");
}
}
else {
try {
exp = Integer.parseInt(sub[i]);
System.out.println("The exp is " + exp);
this.addLink(coeff, exp); // Moved from after this 'else' block.
}
catch (NumberFormatException e) {
System.out.println("Fix This");
}
}
//this.addLink(coeff, exp);//moved from commented out for-loop
}
System.out.println("*******************************************");
}// end constructor
public void addLink(double a, int b) {
if (head == null) {
head = new Term(a, b);
return;
}
Term currNode = head;
while (currNode.next != null) {
currNode = currNode.next;
}
currNode.next = new Term(a, b);
// addLink(a,b);
}
public String toString() {
StringBuilder sb = new StringBuilder();
Term curr = head;
while (curr != null) {
sb.append(curr);
curr = curr.next;
}
return sb.toString();
}
static class Term {
double coeff;
int exp;
Term next;
Term(double c, int e) {
this.coeff = c;
this.exp = e;
this.next = null;
System.out.println("The Coeff " + this.coeff);
System.out.println("The Exp " + this.exp);
}
public String toString() {
return String.format("[C=%.2f,E=%d]-> ", coeff, exp);
}
}
public static void main(String[] args) {
Polyvalues p1 = new Polyvalues();
System.out.println(p1);
}
} // end of class
Running the above code prints the following:
Coeff is 5.0
The exp is 6
The Coeff 5.0
The Exp 6
Coeff is 8.0
The exp is 9
The Coeff 8.0
The Exp 9
Coeff is 1.0
The exp is 9
The Coeff 1.0
The Exp 9
The Coeff 1.0
The Exp 9
*******************************************
[C=5.00,E=6]-> [C=8.00,E=9]-> [C=1.00,E=9]-> [C=1.00,E=9]->

Collision detection inside the same ArrayList

After searching around over the course of a few days, I have not found a solution. I have an ArrayList of collision elements that I want to iterate over and calculate collisions for. I have made several similar attempts, but I am currently stumped.
Collision method (called once a game-tick)
public void iterateCollision()
{
if(iterateBoxes)
{
if(iterateBoxes)
{
for(int i=0;i<boxPool.size();i++)
{
for(int j=i+1;j<boxPool.size();j++)
{
if(!(boxPool.get(i).equals(boxPool.get(j))) && checkCollision(boxPool.get(i), boxPool.get(j)))
{
boxPool.get(i).colliding = true;
boxPool.get(j).colliding = true;
}
}
}
}
}
}
Here is the collision detection method for those of you who would like to review it:
public boolean checkCollision(BaseAABB box1, BaseAABB box2)
{
//This is just to get the center vector of the bounding boxes.
Vector2f c1 = getAABBCenter(box1);
Vector2f c2 = getAABBCenter(box2);
if(Math.abs(c1.x - c2.x) > (box1.width + box2.width)) return false;
if(Math.abs(c1.y - c2.y) > (box1.height + box2.height)) return false;
return true;
}
You forgot to add a condition that i != j
I suspect that you should replace the following condition:
boxPool.get(i) != boxPool.get(j)
with:
!boxPool.get(i).equals(boxPool.get(j))
Further, there's no need to double loop over all the elements, you can always start with j = i + 1 and then you don't have to check that i != j:
for(int i=0;i<boxPool.size();i++)
{
// V
for(int j=i+1;j<boxPool.size();j++) // <-- this line has changed!
{
if(boxPool.get(i) != boxPool.get(j) && checkCollision(boxPool.get(i), boxPool.get(j)))
{
boxPool.get(i).colliding = true;
boxPool.get(j).colliding = true;
}
}
}

Standard 8 Puzzle Depth First Search

I'm working on the standard 8 puzzle solver, and have successfully gotten it to work with BFS. Depth first, on the other hand, infinitely loops. Here's my code for the DFS algoritm:
public static void depthFirstSolver(PuzzleNode initialNode)
{
Stack<PuzzleNode> puzzleStack = new Stack<PuzzleNode>();
puzzleStack.push(initialNode);
HashSet<PuzzleNode> visitedPuzzles = new HashSet<PuzzleNode>();
int[][] goalState = initialNode.getGoalState();
for(PuzzleNode pn : initialNode.childrenPuzzles)
{
pn.generateChildren();
puzzleStack.push(pn);
}
while(!puzzleStack.isEmpty())
{
PuzzleNode temp = puzzleStack.pop();
temp.generateChildren();
LinkedList<PuzzleNode> childrenPuzzles = temp.childrenPuzzles;
if(Arrays.deepEquals(temp.getPuzzleState(), goalState))
{
System.out.println("CURRENT STATE: ");
temp.printPuzzleState();
temp.findCompletePathFromRoot();
break;
}
else
{
if(!visitedPuzzles.contains(temp))
{
for(PuzzleNode pn : childrenPuzzles)
{
pn.generateChildren();
puzzleStack.push(pn);
}
temp.setPuzzleNodeVisited();
temp.printPuzzleState();
}
}
}
}
Here is the generateChildren method:
public void generateChildren()
{
for(int i = 0; i < 4; i++)
{
PuzzleNode temp = new PuzzleNode(puzzleState, this);
if(temp.moveBlank(i) == true)
{
System.out.println("I:" + i); //diag
childrenPuzzles.add(temp);
temp.printPuzzleState(); //diag
}
}
}
Also, here is moveBlank:
public boolean moveBlank(int whichDirectionToMove)
{
//0 = left, 1 = right, 2 = up, 3 = down
boolean[] placesToMove = getMovableBlankPositions();
if(placesToMove[whichDirectionToMove] == false)
return false;
//DIAG
System.out.println("************************************");
//DIAG
switch(whichDirectionToMove)
{
case 0: //left
{
int temp = puzzleState[blankRow][blankCol - 1];
puzzleState[blankRow][blankCol - 1] = 0;
puzzleState[blankRow][blankCol] = temp;
blankCol--;
movementType = "move blank left";
// DIAG
System.out.println("moved blank left");
// DIAG
break;
}
case 1: //right
{
int temp = puzzleState[blankRow][blankCol + 1];
puzzleState[blankRow][blankCol + 1] = 0;
puzzleState[blankRow][blankCol] = temp;
blankCol++;
movementType = "move blank right";
// DIAG
System.out.println("moved blank right");
// DIAG
break;
}
case 2: //up
{
int temp = puzzleState[blankRow - 1][blankCol];
puzzleState[blankRow - 1][blankCol] = 0;
puzzleState[blankRow][blankCol] = temp;
blankRow--;
movementType = "move blank up";
// DIAG
System.out.println("moved blank up");
// DIAG
break;
}
case 3: //down
{
int temp = puzzleState[blankRow + 1][blankCol];
puzzleState[blankRow + 1][blankCol] = 0;
puzzleState[blankRow][blankCol] = temp;
blankRow++;
movementType = "move blank down";
// DIAG
System.out.println("moved blank down");
// DIAG
break;
}
}
return true;
}
In essence, move blank is given a value 0-3, where: 0 = left, 1 = right, 2 = up, 3 = down. The PuzzleNode class contains a linkedlist of potential moves. This list is called childrenPuzzles, and is updated when the generateChildren() method is called. getMovableBlankPositions() returns a 4 index bool array, whose indicies (and t/f value), determine if the space in these directions can be used. BFS works great, it's DFS that infinitely loops. Any suggestions?
Here the main problem is that u are using same puzzleState array to make the child nodes which is wrong way to do it because the same reference is modified everytime you create a child and all child will have the same puzzleState at the end.
Note:- To get around it u must use new puzzleState array to create children.

creating a team of players from a list

Hey im trying to create a random way to pick a team of 4 from a linkedlist and am wondering if this code will work.
heres an example code
public static void enterGame(Client c) {
int n = teamSize;
boolean startNewGame = false;
if(waitingPlayers.size() <= 3) {
return; // not enough players
}
startNewGame = true;
if(startNewGame) {
System.out.println("Starting new game");
for(int i=0; i<n; i++) {
Collections.shuffle(waitingPlayers);
System.out.println("Picking random player");
waitingPlayers.remove(c);
System.out.println("removing from random player list");
players.add(c);
System.out.println("adding player to ingame list");
}
}
}
I would use Collections.shuffle() and a sublist. In order to know if your code works why don't you test it (unit test or just some try)?
Also, this part:
boolean startNewGame = false;
if(waitingPlayers.size() > 3) {
startNewGame = true;
} else {
startNewGame = false;
return;
}
if(startNewGame) {
is over complicated, I would replace it by:
if(waitingPlayers.size() <= 3) {
return; // not enough players
}
Full code:
public static void enterGame(final Client c) {
if(waitingPlayers.size() <= 3) {
return; // not enough players
}
System.out.println("Starting new game");
Collections.shuffle(waitingPlayers);
System.out.println("Picking random players");
// ? to be replaced by the real type of objects inside waitingPlayers
final List<?> picked = waitingPlayers.subList(0, 3);
players.addAll(picked);
waitingPlayers.removeAll(picked);
}
You have a bug - you are picking a number from 0 to n. If n is selected, you will get an out of bounds exception. Other fhan that it seems fine.

Categories