Java Chess: IsInCheck() Method not Functioning Properly - java

I'm writing a chess game in Java have set it up with a Board class that has a 2d array of Square objects. Each square has a height and width (between 0 and 7 inclusive).
I'm writing a method in my Board class that determines whether the passed in player is in check (given the current state of the board).
public boolean isInCheck(Player candidatePlayer) {
String candidateColor = candidatePlayer.getColor();
//get opposite color of candidatePlayer
String oppositeColor = candidateColor.equals("w") ? "b" : "w";
//loop through squares
for (int i = 0; i < myBoard.length; i++) {
for (int j = 0; j < myBoard[i].length; j++) {
//if current square not empty
if (! myBoard[i][j].isEmpty()) {
//if piece at current square is opposite color of candidate player
if (myBoard[i][j].getPiece().getColor().equals(oppositeColor)) {
ArrayList<Square> squares = myBoard[i][j].getPiece().getLegalDestinationSquares(myBoard[i][j]);
//if piece's current legal squares moves contains square of candidatePlayer's king
if (candidateColor.equals("w")) {
if (squares.contains(whiteKingSquare)) {
return true;
}
} else {
if (squares.contains(blackKingSquare)) {
return true;
}
}
}
}
}
}
return false;
}
I've set up the following board position:
bR bKn bB bP bK bP bP bR
bP bP bP bP -- bP bP bP
-- -- -- -- -- -- -- --
-- -- -- -- -- -- -- --
-- -- -- -- -- -- -- --
-- -- -- -- -- -- -- --
wP wP wP wP wQ wP wP wP
wR wKn wB wQ wK wB wKn wR
The black king is currently in check. However, when I run my isInCheckmate(player) method, it returns false. It claims that the black king can move one square down.
Here's my code:
public boolean isCheckmated(Player candidatePlayer, Player other) {
//if candidate player currently in check
if (isInCheck(candidatePlayer)) {
//loop through all squares
for (int i = 0; i <= 7; i++) {
for (int j = 0; j <= 7; j++) {
Square current = myBoard[i][j];
//if current square has one of candidatePlayer's pieces
if (current != null) {
if (current.getPiece().getColor().equals(candidatePlayer.getColor())) {
ArrayList<Square> squares = current.getPiece().getLegalDestinationSquares(current);
//loop through all of that piece's moves
for (Square square : squares) {
//if player can make that move and not in check
if (canMovePiece(current, square, candidatePlayer, other)) {
System.out.println("escape square is at " + square.getHeight() + " " + square.getWidth());
return false;
}
}
}
}
}
}
}
return true;
}
UPDATE: Including code for canMovePiece here:
public boolean canMovePiece(Square start, Square end, Player player1, Player player2) {
//squares are non-null
if (start != null && end != null) {
//get color of moving player
String movingPlayerColor = start.getPiece().getColor();
Player movingPlayer = player1.getColor().equals(movingPlayerColor) ? player1 : player2;
//squares are valid
if (isValidSquare(start.getHeight(), start.getWidth()) && isValidSquare(end.getHeight(), end.getWidth())) {
//if there is a piece at start square and ending square isn't of same color
if (start.getPiece() != null) {
//if end square has a piece on it, must be of different color (or end square is empty)
if (end.getPiece() != null && ! end.getPiece().getColor().equals(movingPlayerColor) || end.getPiece() == null)
//if piece at start can move to square at end
if (start.getPiece().getLegalDestinationSquares(start).contains(end)) {
//store captured piece so we can undo move later
Piece captured = end.getPiece();
//make move
movePiece(start, end);
boolean playerInCheck = isInCheck(movingPlayer);
//if player who made move not in check
if (! playerInCheck) {
//undo move
movePiece(end, start);
if (captured != null) {
end.setPiece(captured);
}
//return true
return true;
}
//else (player who made move is in check)
else {
//undo move
movePiece(end, start);
if (captured != null) {
end.setPiece(captured);
}
return false;
}
}
}
}
}
return false;
}
I still can't figure out why my code thinks the king is out of check if it moves a square down (where it's still in check by the white queen).
Any help much appreciated!
-Mariogs

Related

A* algorithm infinite while-loop

I've been attempting to follow some pseudocode, namely
https://www.geeksforgeeks.org/a-search-algorithm/ &
http://mat.uab.cat/~alseda/MasterOpt/AStar-Algorithm.pdf ,
to create an A star pathfinding algorithm for a four-directional tile/cell-based map with obstacles. I understand the concept, and I could definitely explain how it should work in words/images, but putting it into code is proving challenging. For a few days now whenever I've run my program it crashes and I have to manually stop the application. I believe this is due to an infinite while-loop. This confuses me because the program should exit the while-loop once its found the end destination, but obviously that isn't working. This is the code which I think should make it exit the while-loop once the destination is found:
if (n.getX() == end.getX() && n.getY() == end.getY()) {
currentNode = n;
break;
}
I hope this isn't too much code to put in this post, but this is the meat of my algorithm with comments on what I think each piece is doing:
public void attempt2() {
double leastF = Integer.MAX_VALUE;
// Initializes the starting Node and, in the beginning, currentNode is the same
// as the starting node
Node start = new Node(r.getCell());
Node currentNode = start;
start.setParent(start);
closed.add(start);
open.add(start);
start.setEnd(destinationCP);
start.calculateH();
start.isCalculatedH();
while (open.size() > 0) {
// Finds the node with the least F score on Open
for (Node n : open) {
// Calculates the H-score if it hasn't been already
if (n.haveNotCalculatedH()) {
n.setEnd(destinationCP);
n.calculateH();
n.isCalculatedH();
}
// Calculates the g-score, with 1 being the value/distance of a cell
n.setAdditiveDistanceG(n.getAdditiveDistanceG() + 1);
// Calculates the F-score
n.calculateF();
// Actually finds the least F score in the open list and sets currentNode to the
// node with the least F
if (n.getTotalCostF() < leastF) {
leastF = n.getTotalCostF();
currentNode = n;
}
}
//
// Creates easy-access variables for the x and y values of the node on open with
// the least F score
int thisX = currentNode.getX();
int thisY = currentNode.getY();
// if this cell (cell in open w least F) is the end destination cell, stop the calculations
if (thisX == end.getX() && thisY == end.getY()) {
break;
}
//
// Generate 1-4 successors if Robot can pass into the cell
if (World.getCell(thisX + 1, thisY).canEnter(r)) {
successors.add(new Node(World.getCell(thisX + 1, thisY)));
}
if (World.getCell(thisX, thisY + 1).canEnter(r)) {
successors.add(new Node(World.getCell(thisX, thisY + 1)));
}
if (World.getCell(thisX - 1, thisY).canEnter(r)) {
successors.add(new Node(World.getCell(thisX - 1, thisY)));
}
if (World.getCell(thisX, thisY - 1).canEnter(r)) {
successors.add(new Node(World.getCell(thisX, thisY - 1)));
}
//
/*
* Loops through each of the 1-4 neighbors to currentNode (I need to add in to
* erase & add to open/closed every one in here so its empty before new ones are
* generated
*/
for (Node n : successors) {
double successorCurrentCost = 0;
// if this successor is already in the closed list, skip doing all the code for
// this node and add this successor's parent (currentNode) to the closed list
if (isInClosed(n)) {
continue;
}
// if this is the goal/end node, exit the 'successors' for-loop. the step that
// follows this (exiting the loop) is that this particular node/successor is
// added to the closed list
if (n.getX() == end.getX() && n.getY() == end.getY()) {
currentNode = n;
break;
}
//
// Calculates the F cost for each successor to currentNode
if (n.haveNotCalculatedH()) {
n.setEnd(destinationCP);
n.calculateH();
n.isCalculatedH();
}
n.setAdditiveDistanceG(n.getAdditiveDistanceG() + currentNode.getAdditiveDistanceG());
n.calculateF();
successorCurrentCost = n.getTotalCostF();
//
if (!isInOpen(n) && n.getAdditiveDistanceG() > successorCurrentCost
|| n.getAdditiveDistanceG() > successorCurrentCost && !isInClosed(n)) {
open.add(n);
if (n.haveNotCalculatedH()) {
n.setEnd(destinationCP);
n.calculateH();
n.isCalculatedH();
}
} else if (isInClosed(n) && n.getAdditiveDistanceG() <= successorCurrentCost) {
successorCurrentCost = n.getAdditiveDistanceG();
n.setParent(currentNode);
} else {
successorCurrentCost = n.getAdditiveDistanceG();
n.setParent(currentNode);
}
if (isInClosed(n)) {
closed.remove(n);
open.add(n);
}
}
closed.add(currentNode);
if (thisX == end.getX() && thisY == end.getY()) {
break;
}
}
if (currentNode.getMyCell() != this.destinationCP) {
System.out.println("ERROR: open list is empty");
return;
} else {
createPath();
}
}
I am aware that there are a few things that should be changed in this code, however I am most concerned about the while loop never being terminated. Any other comments about my code are appreciated but definitely not necessary.

Java maze won't print

I have to make a maze for a java assignment, and I was able to finish most of it. I was provided with an outline of the code that had all the methods. Can someone help me? My issue is that the maze wont print out, and I can't figure out why.
package maze;
public class Maze {
private char direction;
private int r; // x position of the mouse
private int c; //y position of the mouse
private boolean exitFound = false;
public Maze(int[][] arrMaze) {
this.r = arrMaze.length - 1;
this.c = 0;
}
//Prints out the maze without solution
public void displayMaze(int[][] arrMaze)
{
//display the maze putting blank spaces where there are 1's in the array and putting
//another symbol where there are 0's to show the maze without the solution
for(int i=0; i<arrMaze.length; i++){
System.out.println(" ");
for(int j=0; j<arrMaze[i].length; j++){
if(arrMaze[i][j] == 0){
System.out.print("#");
} if(arrMaze[i][j] == 1) {
System.out.print(" ");
} if(arrMaze[i][j] == 2){
System.out.print("#");
} if(arrMaze[i][j] == 3){
System.out.println("~");
}
}
}
}
//displays the Maze with the path taken
public void displayPath(int[][] arrMaze)
{
//show the user how far the mouse has gone since the start.
//The path the mouse has gone will be filled in but the path ahead will not.
for (int i = 0; i < arrMaze.length; i++) {
System.out.println(" ");
for (int j = 0; j < arrMaze[i].length; j++) {
if (arrMaze[i][j] == 3) {
System.out.print("#");
} else if (arrMaze[i][j] == 2) {
System.out.print("~");
} else if (arrMaze[i][j] == 0) {
System.out.print("#");
} else {
}
}
}
}
public boolean takeStep(int[][] newMaze) {
// moveNorth(newMaze)
for (int i = 0; i < newMaze.length; i++) {
System.out.println(" ");
for (int j = 0; j < newMaze[i].length; j++) {
if (newMaze[r][c] == 3) {
moveNorth(newMaze);
System.out.print("~");
} else if (newMaze[r][c] == 2) {
System.out.print("#");
} else {
}
}
}
return isAnExit(newMaze);
}
public void moveNorth(int[][] arrMaze) {
//complete the code here
/*method will check for a 0 or a 1 in the position above the current position
* and then if not a 0 will change the current position to the row above it, but in the same column.
*/
if (arrMaze[r][c - 1] != 0) {
arrMaze[r][c - 1] = 3;
arrMaze[r][c + 1] = 2;
} else {
moveSouth(arrMaze);
}
displayPath(arrMaze);
}
public void moveSouth(int[][] arrMaze)
{
//method will check for a 0 or a 1 in the position below the current position and then if not a 0
//it will change the current position to the row below it, but in the same column.
if (arrMaze[r][c + 1] != 0) {
arrMaze[r][c + 1] = 3;
arrMaze[r][c + 1] = 2;
} else {
moveNorth(arrMaze);
}
displayPath(arrMaze);
}
public void moveEast(int[][] arrMaze) {
//method will check for a 0 or a 1 in the position to the right of  the current position and then if
//not a 0 will change the current position to the column to the right but the same row.
if (arrMaze[r + 1][c] != 0) {
arrMaze[r + 1][c] = 3;
arrMaze[r - 1][c] = 2;
} else {
moveWest(arrMaze);
}
displayPath(arrMaze);
}
public void moveWest(int[][] arrMaze) {
//method will check for a 0 or a 1 in the position to the left of  the current position and then if
//not a 0 will change the current position to the column to the left but the same row.
if (arrMaze[r - 1][c] != 0) {
arrMaze[r - 1][c] = 3;
arrMaze[r + 1][c] = 2;
} else {
}
displayPath(arrMaze);
}
private boolean isAnExit(int[][] arrMaze) {
//method will return true if the user arrives into the last column of the array because there is only one
//location in the last column that is a 1, so if the user reaches the array[i].length then that means that it found an exit.
if (arrMaze[r][c] > arrMaze.length) {
exitFound = true;
} else {
exitFound = false;
}
return exitFound;
}
//finds the path without stopping at every step
//method will show the complete path from start to finish of the maze and the suggested route to the end.
public void findExit(int[][] arrMaze) {
if (arrMaze[r][c] > arrMaze.length) {
for (int i = 0; i < arrMaze.length; i++) {
takeStep(arrMaze);
}
}
}
}
This is the test code. I was provided the test code, and I haven't changed it.
package maze;
import java.util.Scanner;
public class TestMaze
{
public static void main(String[] args)
{
int[][] mazeArray = {
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0},
{0,0,0,1,1,1,1,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,1,1,1,1},
{0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0},
{0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0},
{1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
Maze myMaze = new Maze(mazeArray);
boolean keepAsking = true;
Scanner scan = new Scanner(System.in);
String input = "";
myMaze.displayPath(mazeArray);
System.out.println("Maze");
do {
System.out.println("T = Take a step | S = Show path | Q = Quit");
System.out.print("Enter command: ");
input = scan.nextLine();
input.trim();
input.toLowerCase();
if(input.equals("t")) {
keepAsking = !myMaze.takeStep(mazeArray);
System.out.println("Which direction would you like to go? N, S, E, W?");
String direction = scan.nextLine();
if(direction.equalsIgnoreCase("n"))
myMaze.moveNorth(mazeArray);
if(direction.equalsIgnoreCase("s"))
myMaze.moveSouth(mazeArray);
if(direction.equalsIgnoreCase("e"))
myMaze.moveEast(mazeArray);
if(direction.equalsIgnoreCase("w"))
myMaze.moveWest(mazeArray);
}
else if(input.equals("s")) {
myMaze.findExit(mazeArray);
keepAsking = false;
}
else if(input.equals("q")) {
keepAsking = false;
}
else {
System.out.println("ERR: Invalid input");
}
} while(keepAsking);
System.out.println("Quitting program...");
scan.close();
}
}
You need to call displayMaze() (in displayPath()) to print it.
Currently, you're not calling the method, meaning that your code will never print the maze as it's no being instructed to.
Also, where are you assigning values to r and c? I think you meant to use i and j in your displayPath() method ([i][j] instead of [r][c]).
I imagine you're throwing an error somewhere because your r and c values are undefined everywhere they are used. Try adding code to initialize and update these values, then you should see your maze print.

player goes through walls while jumping (JAVA)

I am trying to make a donkey kong game.
Currently, I have a boolean called jump which tells that game if the player is jumping or not, when the space bar is pressed.
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_SPACE){
StartJump();
}
}
StartJump: Makes the sprite start jumping by changing velocity. It also changes the jump boolean to true.
public void StartJump() {
if (onground) {
velocityY = -4;
onground = false;
jump = true;
}
}
KeyReleased:
public void keyReleased(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_SPACE){
EndJump();
}
}
EndJump: Sets jump to false
public void EndJump() {
if(velocityY < -6.0)
velocityY = -6;
jump = false;
}
The problem occurs when you hold down the spacebar, jump is set to true.
Which then causes the forloop which sets the Y position of Mario to not work and he falls through the floor.
Loop: bricks just contains rectangles for Mario to stand on
for(int i = 0; i < bricks.size(); i++) {
if(marHitBox.intersects(bricks.get(i)) && !mario.getClimb() && !mario.getJump() && marHitBox.intersects(jump.get(i))) {
mario.setMarY((int)bricks.get(i).getY()-40);
mario.setVeloY(0f);
mario.setOnGround(true);
}
}
It is the !mario.getJump() that is causing the problem. Is there any way to see if the spacebar is held for more than x milliseconds to make jump = false?
Try measuring the passing time between the spacebar is pressed and released, it will fit your need.
I think just a check would make it go away
public void StartJump(){
if (!jump && onground){
velocityY = -4;
onground = false;
jump = true;
}
}

Collision detection not working with my brick breaker program?

My program has been experiencing an odd bug i just cannot seem to fix. In summary, whenever I switch two if statements, only the one coming afte tthe first one will work.
Example: (The ball will successfully collide with the top, but won't with the bottom.)
public void update()
{
if(enemies != null)
{
for(Enemy e : enemies)
if(c.getBall().getHitbox().intersects(e.getHitbox()))
{
if(e.collidedBottom())
c.getBall().setSpeedY((c.getBall().ballSpeed));
if(e.collidedTop())
c.getBall().setSpeedY(-(c.getBall().ballSpeed));
deadEnemies.add(e);
}
enemies.removeAll(deadEnemies);
}
Now if i switched the positions of the two if statements like so;
if(e.collidedTop())
c.getBall().setSpeedY(-(c.getBall().ballSpeed));
if(e.collidedBottom())
c.getBall().setSpeedY((c.getBall().ballSpeed));
The ball will successfully react the way it should when colliding with the bottom, but not with the top. Here is the two collision methods:
public boolean collidedBottom()
{
if(c.getBall().getBallY() <= enemy.y + enemy.height &&
c.getBall().getBallX() + c.getBall().getHitbox().width >= enemy.x
&& c.getBall().getBallX() <= enemy.x + enemy.width)
return true;
return false;
}
public boolean collidedTop()
{
if(c.getBall().getBallY() + c.getBall().getHitbox().height >= enemy.y &&
c.getBall().getBallX() + c.getBall().getHitbox().width >= enemy.x
&& c.getBall().getBallX() <= enemy.x + enemy.width)
return true;
return false;
}
Enemy refers to the current focused block in the loop.

To test, using a backtracking algorithm, if a mouse can escape from a rectangular maze

This program has is meant to create and solve a mouse escape route from a maze, by reading from a text file.There is a Maze class which is basically a 2D array of MazeElements, the MazeElements contains a char variable and a position object; the Position holds the co-ordinates of each element on the 2D-array.
So far, the program effectively reads in and creates the 2D array. The problem lies in the backTracking algorithm. I am using a stack to implement the back track but the backtrack seems to only loop once from the output. I don't know if you can notice something from the code below:
import java.io.;
import java.util.;
public class MazeSolver
{
public static void main (String [] parms)
{
Maze maze = new Maze();
maze.displayMaze();
maze.backTracking();
maze.displayMaze();
}
}
//**********************************
//*******Position class*************
//**********************************
class Position
{
private int row;
private int col;
public Position()
{
row =0;
col =0;
}
public Position (int x, int y)
{
row = x;
col = y;
}
public void setRow(int x)
{
row = x;
}
public void setCol(int y)
{
col = y;
}
public int getRow()
{
return row;
}
public int getCol()
{
return col;
}
//NOTE: wrote for testing purposes, to see the mouse and exit positions
public String getPosition()
{
return row + ", " + col;
}
}//end Position
//**********************************
//*******Maze element class*********
//**********************************
class MazeElement
{
private char letter;
private Position prevPosition;
public MazeElement(char c, Position p)
{
this.letter = c;
this.prevPosition = p;
}
public char getLetter()
{
return letter;
}
public Position getPosition()
{
return prevPosition;
}
public void setPosition(Position p)
{
this.prevPosition = p;
}
public void setLetter(char c)
{
this.letter = c;
}
public void printElement()
{
System.out.print(letter + " ");
}
}//end MazeElement
//**********************************
//*******Maze class*****************
//**********************************
class Maze
{
private MazeElement [][] maze;
private int numRows;
private int numCols;
private Position start;
private Position exit;
BufferedReader inFile;
Scanner kbd = new Scanner(System.in);
String inLine;
String fileName;
String [] tokens;
public Maze()
{
try
{
System.out.println("Input file name");
fileName = kbd.next();
inFile = new BufferedReader(new FileReader(fileName));
inLine = inFile.readLine();
tokens = inLine.trim().split("\\s+");
numRows = Integer.parseInt(tokens[0]);
numCols = Integer.parseInt(tokens[1]);
maze = new MazeElement[numRows][numCols];
for(int row = 0; inLine != null && row < numRows; row++)
{
inLine = inFile.readLine();
tokens = inLine.trim().split("\\s+");
for(int col = 0; col < numCols; col++)
{
maze[row][col] = new MazeElement(tokens[col].charAt(0),null);
}
}
inFile.close();
//finding m and e from the maze
for (int i = 0; i < maze.length; i++)
{
for (int j = 0; j < maze[i].length; j++)
{
char letter = maze[i][j].getLetter();
if(letter == 'm')
{
start = new Position(i,j);
}
if(letter == 'e')
{
exit = new Position(i,j);
}
}
}
}//end try block
catch (IOException ioe)
{
System.out.println(ioe.getMessage());
}
}//end public Maze()
public void backTracking()
{
Stack<Position> theStack = new Stack<Position>();//initialise stack
Position goal = exit;
Position curr;
MazeElement north, south, east, west;
int currRow, currCol;
curr = null;
boolean foundGoal = false;
theStack.push(start);
while((!foundGoal) && (!theStack.isEmpty()))
{
curr = theStack.pop();
currRow = curr.getRow();
currCol = curr.getCol();
//check neighbouring positions
east = maze[currRow][currCol+1];
south = maze[currRow+1][currCol];
west = maze[currRow][currCol-1];
north = maze[currRow-1][currCol];
//searching clockwise
//setting visited positions to '.', open = '0', wall = '1', exit==goal = 'e'
if(isValidPosition(east))
{
if(east.getLetter() == 'e')
{
east.setPosition(curr);
theStack.push(east.getPosition());
foundGoal = true;
}
else if((!foundGoal)&&(east.getLetter() == '0')&& (east.getLetter() != '.'))
{
east.setLetter('.');
east.setPosition(curr);
theStack.push(east.getPosition());
}
}
else if(isValidPosition(south))
{
if(south.getLetter() == 'e')
{
south.setPosition(curr);
theStack.push(south.getPosition());
foundGoal = true;
}
else if((!foundGoal)&&(south.getLetter() == '0')&& (south.getLetter() != '.'))
{
south.setLetter('.');
south.setPosition(curr);
theStack.push(south.getPosition());
}
}
else if(isValidPosition(west))
{
if(west.getLetter() == 'e')
{
west.setPosition(curr);
theStack.push(west.getPosition());
foundGoal = true;
}
else if((!foundGoal)&&(west.getLetter() == '0')&& (west.getLetter() != '.'))
{
west.setLetter('.');
west.setPosition(curr);
theStack.push(west.getPosition());
}
}
else if(isValidPosition(north))
{
if(north.getLetter() == 'e')
{
north.setPosition(curr);
theStack.push(north.getPosition());
foundGoal = true;
}
else if((!foundGoal)&&(north.getLetter() == '0')&& (north.getLetter() != '.'))
{
north.setLetter('.');
north.setPosition(curr);
theStack.push(north.getPosition());
}
}
}//end while
}
public void displayMaze()
{
for (int i = 0; i < maze.length; i++)
{
for (int j = 0; j < maze[i].length; j++)
{
maze[i][j].printElement();
}
System.out.println();
}
System.out.println("start is at " + start.getPosition());
System.out.println("exit is at " + exit.getPosition());
}//displayMaze()
public boolean isValidPosition(MazeElement element)
{
char wall = '1';
return (element.getLetter() != wall);
}
}
//**********************************
//*******Stack<E> class*************
//**********************************
class Stack<E>
{
protected Node<E> head;
public Stack()
{
head = null;
}
public boolean isEmpty()
{
return (head == null);
}
public void push(E item)
{
head = new Node<E>(item, head);
}
public E top()
{
E topItem = null;
if (head != null) topItem = head.getData();
return topItem;
}
public E pop()
{
E topItem = top();
if (head != null) head = head.getNext();
return topItem;
}
}
//**********************************
//*******Node class*****************
//**********************************
class Node <E>
{
private E data;
private Node<E> next;
public Node ()
{
//initializing everything to null at first
next = null;
data = null;
}
public Node(E data, Node <E> n)
{
this.data = data;
this.next = n;
}
public E getData()
{
return data;
}
public Node <E> getNext()
{
return next;
}
public void setNext(Node <E> next)
{
this.next = next;
}
}
My input file is the following:
6 5
1 1 1 1 1
1 0 0 e 1
1 1 1 0 1
1 m 1 0 1
1 0 0 0 1
1 1 1 1 1
When I print the maze after I call the backTrack() method, my Maze(with m and e positions) becomes:
1 1 1 1 1
1 0 0 e 1
1 1 1 0 1
1 m 1 0 1
1 . 0 0 1
1 1 1 1 1
start is at 3, 1
exit is at 1, 3
The issue is that I do not understand why my curr doesn't move beyond the point '.' in the output. Please help?
Here:
if(isValidPosition(east))
{
if(east.getLetter() == 'e')
{
east.setPosition(curr);
theStack.push(east.getPosition());
foundGoal = true;
}
else if((!foundGoal)&&(east.getLetter() == '0')&& (east.getLetter() != '.'))
{
east.setLetter('.');
theStack.push(east.getPosition());
}
}
Original :
From what I can tell, the only thing that has been pushed into theStack is start. So, curr == start. Then, in your conditions, if it meets the directions you do:
east.setPosition(curr);
theStack.push(east.getPosition());
(Or whichever direction it tests on, in this case it's actually south).
Remember, the first time curr == start, so you're setting east.setPosition == curr == start, which means you push back to the stack start.
Now, the code runs again with only 1 thing in the theStack and it's the same as it was before, EXCEPT, the character below start is now a '.', so there are no valid directions and your while loop breaks.
To fix the code, you'll have to push to theStack a Position whose values are the direction's and not update the direction position.
I made a few changes to your code, first to the map loading function, so that every element had a position. You can get rid of this and use rheStack.push(new Position(row,col)); but i was too lazy.
for(int row = 0; inLine != null && row < numRows; row++)
{
inLine = inFile.readLine();
tokens = inLine.trim().split("\\s+");
for(int col = 0; col < numCols; col++)
{
maze[row][col] = new MazeElement(tokens[col].charAt(0),new Position(row,col));
}
}
The next change is to the backtracking code. Now in essence you can backtrack using only a stack, however it is not enough to just store the places you have been. For example, after if you first went east and then west, then you need to store that on the stack as well. This makes backtracking more complicated, however programming languages gives us a much easier way of dealing with stacks - recursion.
All the parameters passed to a function, and all the temporaries it creates, are stored on a special stack - the program stack. This is the same stack referenced in StackOverflow. Therefore recursive functions have all the same strucutre as a backtracking alogorithm.
So I broke you backtracking algorithm to make it recursive
public void backTracking()
{
Stack<Position> theStack = new Stack<Position>();//initialise stack
theStack.push(start);
//pass it the stack and the goal
backTrackingRecursive(theStack, exit);
}
public boolean backTrackingRecursive(Stack<Position> theStack, Position goal)
{
//displayMaze();
Position curr = theStack.top();
int currRow = curr.getRow();
int currCol = curr.getCol();
//setting visited positions to '.', open = '0', wall = '1', exit==goal = 'e'
for(int i = 0; i != 4; i++)
{
//forget this code, it is only to avoid writing out north, south, etc
int col = currCol;
int row = currRow;
if(i%2 == 1)
col += ((i==1)?1:-1);
else
row += ((i==2)?1:-1);
//check it is a valid position, if not continue
if(row < 0 || row >= numRows || col < 0 || col >= numCols) continue;
MazeElement next = maze[row][col];
if(next.getLetter() == 'e')
{
theStack.push(next.getPosition());
return true;
}
else if(next.getLetter() == '0')
{
theStack.push(next.getPosition());
next.setLetter('.');
if(backTrackingRecursive(theStack,goal))
{
//success!
return true;
} else {
//try a different path
next.setLetter('0');
theStack.pop();
}
}
}
return false;
}
The backTrackingRecursive function does all the work, and we simply push the next position on to the stack before continuing. We don't even need to have the stack at all but I kept it for simplicity.
Output:
1 1 1 1 1
1 0 0 e 1
1 1 1 0 1
1 m 1 0 1
1 0 0 0 1
1 1 1 1 1
start is at 3, 1
exit is at 1, 3
1 1 1 1 1
1 0 0 e 1
1 1 1 . 1
1 m 1 . 1
1 . . . 1
1 1 1 1 1
start is at 3, 1
exit is at 1, 3
this works perfectly!!!! i followed the comments from the first answer and found this solution! thank you #CreationEdge
if(isValidPosition(east))
{
if(east.getLetter() == 'e')
{
foundGoal = true;
}
if((!foundGoal)&&(east.getLetter() == '0')&& (east.getLetter() != '.'))
{
east.setLetter('.');
east.setPosition(curr);
theStack.push(new Position(curr.getRow(), curr.getCol()+1));
}
}
if(isValidPosition(south))
{
if(south.getLetter() == 'e')
{
System.out.println(south.getLetter());
foundGoal = true;
}
if((!foundGoal)&&(south.getLetter() == '0')&& (south.getLetter() != '.'))
{
south.setLetter('.');
south.setPosition(curr);
theStack.push(new Position(curr.getRow() + 1, curr.getCol()));
}
}
if(isValidPosition(west))
{
if(west.getLetter() == 'e')
{
foundGoal = true;
}
if((!foundGoal)&&(west.getLetter() == '0')&& (west.getLetter() != '.'))
{
west.setLetter('.');
west.setPosition(curr);
theStack.push(new Position(curr.getRow(), curr.getCol()-1));
}
}
if(isValidPosition(north))
{
if(north.getLetter() == 'e')
{
foundGoal = true;
}
if((!foundGoal)&&(north.getLetter() == '0')&& (north.getLetter() != '.'))
{
north.setLetter('.');
north.setPosition(curr);
theStack.push(new Position(curr.getRow() - 1, curr.getCol()));
}
}

Categories

Resources