Maze Path-Finder Recursion & Backtracking - java

I am trying to make an algorithm that finds a path for a maze and prints out the failed paths as well. The output should look like this:
Where # is a wall, * is a failed path, and # is a working path to the end of the maze
My pathfinding method is not completely finding all the paths:
public boolean findPath(int row, int col) {
if (maze.get(row)[col] == 'E'){
return true;
}
if (maze.get(row)[col] == '#' || maze.get(row)[col] == '*') {
return false;
}
else {
if (maze.get(row)[col] != 'S'){
maze.get(row)[col] = '*';
}
if (col - 1 >= 0){
if (findPath(row, col - 1)) {
maze.get(row)[col] = '#';
return true;
}
}
if (row - 1 >= 0){
if (findPath(row - 1, col)) {
maze.get(row)[col] = '#';
return true;
}
}
if (row + 1 < maze.size()){
if (findPath(row + 1, col)) {
maze.get(row)[col] = '#';
return true;
}
}
if (col + 1 < maze.get(row).length) {
if (findPath(row, col + 1)) {
maze.get(row)[col] = '#';
return true;
}
}
}
return false;
}
Attached is the output, where not all #'s are placed and some are not true. Also, it overrides the start point. Any solutions?

Related

Recursion Showing Adjacent Blank Mines in Minesweeper

I am fairly new to Java and I have been working on a Minesweeper game. I am trying to get the adjacent cells to be revealed recursively when an empty cell is clicked. I do this by calling showCell() shown below:
Cells array declaration and population:
private final Cell[][] cells;
public void newGame()
{
numMinesLeft = NUM_MINES;
numCellsLeft = NUM_ROWS * NUM_COLS;
hasHitMine = false;
Cell[] newCells = new Cell[NUM_ROWS * NUM_COLS];
int k = 0; // index in newCells
// create the cells with the mines
while (k < NUM_MINES && k < newCells.length)
{
newCells[k] = new Cell(MINE);
k++;
}
// create the cells without the mines
while (k < newCells.length)
{
newCells[k] = new Cell();
k++;
}
// uniformly mix newCells
for (k = newCells.length; k > 1;)
{
int r = generator.nextInt(k);
k--;
// interchange newCells[r] and newCells[k]
Cell temp = newCells[k];
newCells[k] = newCells[r];
newCells[r] = temp;
}
k = 0;
// place cells into the cells array
for (int i = 0; i < NUM_ROWS; ++i)
{
for (int j = 0; j < NUM_COLS; ++j)
{
cells[i][j] = newCells[k];
k++;
}
}
for(int i = 0; i<NUM_ROWS; i++)
{
for (int j = 0; j<NUM_COLS; j++)
{
int numOfBorderMines = 0;
if (cells[i][j].value != MINE)
{
if(isInTheGrid(i-1, j) == true)
{
if (cells[i-1][j].value == MINE )
{
numOfBorderMines++;
}
}
if(isInTheGrid(i+1, j) == true)
{
if (cells[i+1][j].value == MINE )
{
numOfBorderMines++;
}
}
if(isInTheGrid(i, j - 1) == true)
{
if (cells[i][j - 1].value == MINE )
{
numOfBorderMines++;
}
}
if(isInTheGrid(i, j + 1) == true)
{
if (cells[i][j + 1].value == MINE )
{
numOfBorderMines++;
}
}
if(isInTheGrid(i - 1, j + 1) == true)
{
if (cells[i - 1][j + 1].value == MINE )
{
numOfBorderMines++;
}
}
if(isInTheGrid(i + 1, j - 1) == true)
{
if (cells[i + 1][j - 1].value == MINE )
{
numOfBorderMines++;
}
}
if(isInTheGrid(i + 1, j + 1) == true)
{
if (cells[i + 1][j + 1].value == MINE )
{
numOfBorderMines++;
}
}
if(isInTheGrid(i - 1, j - 1) == true)
{
if (cells[i - 1][j - 1].value == MINE )
{
numOfBorderMines++;
}
}
cells[i][j].value = numOfBorderMines;
}
}
}
}
toggleFlag()
public void toggleFlag(int row, int col)
{
if (isCellShowing(row, col) || isOver()) return;
if (isCellFlagged(row, col))
{
// unflag cell
cells[row][col].hasFlag = false;
numMinesLeft++;
numCellsLeft++;
}
else if (numMinesLeft > 0)
{
// flag cell
cells[row][col].hasFlag = true;
numMinesLeft--;
numCellsLeft--;
}
ui.updateCell(row, col);
}
showCell()
public void showCell(int row, int col)
{
// checks is cell has been flagged or if the game is over, otherwise it reveals the cell
if(isCellFlagged(row, col) == true || isOver())
{
return;
}
else
{
cells[row][col].isShowing = true;
ui.updateCell(row, col);
}
// checks if cell has a mine and triggers hasHitMine otherwise subtracts 1 from class variable numCellsLeft
if (cells[row][col].value == MINE)
{
hasHitMine = true;
}
else
{
numCellsLeft--;
}
// if there are no mines adjacent, recursively reveal the adjacent cells
if(cells[row][col].value == 0)
{
showCell(row + 1, col);
showCell(row - 1, col);
showCell(row, col + 1);
showCell(row, col -1);
showCell(row + 1, col - 1);
showCell(row + 1, col + 1);
showCell(row - 1, col - 1);
showCell(row - 1, col + 1);
}
}
The problem I am having is when I hit this portion of the code and click an empty cell, it reveals all cells adjacent continuously down a column or a row in one direction. I can't get my implementation of recursion right, perhaps I am approaching it wrong. My idea was to reveal each adjacent cell according to the grid position.
I solved my problem by implementing Tail Recursion. Here is my updated showCell() method and tail recursion method:
public void showCell(int row, int col)
{
// checks is cell has been flagged or if the game is over, otherwise it reveals the cell
if(isCellFlagged(row, col) == true || isOver())
{
return;
}
else
{
cells[row][col].isShowing = true;
ui.updateCell(row, col);
}
// checks if cell has a mine and triggers hasHitMine otherwise subtracts 1 from class variable numCellsLeft
if (cells[row][col].value == MINE)
{
hasHitMine = true;
}
else
{
numCellsLeft--;
}
// if there are no mines adjacent, recursively reveal the adjacent cells
if(cells[row][col].value == 0)
{
if(isInTheGrid(row - 1, col) == true)
{
showCell(row - 1, col, cells[row - 1][col].isShowing);
}
if(isInTheGrid(row + 1, col) == true)
{
showCell(row + 1, col, cells[row + 1][col].isShowing);
}
if(isInTheGrid(row, col - 1) == true)
{
showCell(row, col - 1, cells[row][col - 1].isShowing);
}
if(isInTheGrid(row, col + 1) == true)
{
showCell(row, col + 1, cells[row][col + 1].isShowing);
}
if(isInTheGrid(row + 1, col - 1) == true)
{
showCell(row + 1, col - 1, cells[row + 1][col - 1].isShowing);
}
if(isInTheGrid(row - 1, col + 1) == true)
{
showCell(row - 1, col + 1, cells[row - 1][col + 1].isShowing);
}
if(isInTheGrid(row + 1, col + 1) == true)
{
showCell(row + 1, col + 1, cells[row + 1][col + 1].isShowing);
}
if(isInTheGrid(row - 1, col - 1) == true)
{
showCell(row - 1, col - 1, cells[row - 1][col - 1].isShowing);
}
}
else
{
return;
}
}
public boolean isInTheGrid(int x, int y)
{
if (x < 0 || y < 0) return false;
if(x >= NUM_ROWS || y >= NUM_COLS) return false;
return true;
}
public void showCell(int row, int col, boolean isShown)
{
if (isShown != true)
{
cells[row][col].isShowing = true;
ui.updateCell(row, col);
}
else
{
return;
}
}
When you call show cell for surrounding cells, you want to make sure that you don't re-show the cell you called it from, or past cells that were shown from the previous calls in the recursion stack.
If I understood your question correctly, I believe you are referring the case in Minesweeper where if you click on an empty cell, then it will reveal the adjacent empty cells.

how to find if 2 elements of an array contains a certain value

Somehow I managed to find one certain value with the below code but how can I search if an array has value 1 and the right next value is 3
unlucky1([1, 3, 4, 5]) → true
unlucky1([2, 1, 3, 4, 5]) → true
unlucky1([1, 1, 1]) → false
public boolean unlucky1(int[] nums) {
//int[] a = new int[] {1,3};
for(int i: nums)
{
if (i == 1 )
return true;
}
return false;
}
You can use a state machine:
boolean wasOne = false;
for (int i: nums) {
if (i == 3 && wasOne) {
return true;
}
wasOne = i == 1;
}
return false;
The for-each loop hides the iterator (or index here), so you can't get the current value and check the next value at the same time. Use a standard loop. Also, since you don't access any field's - you could make the method static. Like,
public static boolean unlucky1(int[] nums) {
for (int i = 0; i < nums.length - 1; i++) {
if (nums[i] == 1 && nums[i + 1] == 3) {
return true;
}
}
return false;
}
And, in Java 8+, you could express that with an IntStream and anyMatch like
public static boolean unlucky1(int[] nums) {
return IntStream.range(0, nums.length - 1)
.anyMatch(i -> nums[i] == 1 && nums[i + 1] == 3);
}
Note the nums.length - 1 in both cases, that is to ensure the nums[i + 1] doesn't exceed the length of the nums array on the conditional check.
Updated because you did not add the next condition - which was
in the first 2 or last 2 positions in the array.
That checker is strict. Follow the instructions carefully. I get (working)
public boolean unlucky1(int[] nums) {
int len = (nums == null) ? 0 : nums.length;
for (int i = 0; i < 2 && i + 1 < len; i++) {
if (nums[i] == 1 && nums[i + 1] == 3) {
return true;
}
}
if (len - 2 <= 0) {
return false;
}
for (int i = len - 2; i + 1 < len; i++) {
if (nums[i] == 1 && nums[i + 1] == 3) {
return true;
}
}
return false;
}
Which you could also implement without loops at all, like
public boolean unlucky1(int[] nums) {
int len = (nums != null) ? nums.length : 0;
if (len < 2) {
return false;
}
if ((nums[0] == 1 && nums[1] == 3) || (nums[1] == 1 && nums[2] == 3)) {
return true;
}
return len > 3 && ((nums[len - 4] == 1 && nums[len - 3] == 3) //
|| (nums[len - 2] == 1 && nums[len - 1] == 3));
}
I swapped the ternary order, but that's not important.
Try with basic for loop:
public boolean unlucky1(int[] nums) {
boolean match = false;
for (int i = 0; nums.length - 1 > i; i++) {
if (1 == nums[i] && 3 == nums[i + 1]) {
match = true;
break;
}
}
return match;
}
try this updated code.
arroding to your question
public boolean unlucky1(int[] nums) {
int count = 0;
for(int i=0;i<nums.length;i++)
{
if (nums[i] == 1 && (i+1)<nums.length && nums[i+1]==3){
if(i<2){
return true;
}
else if(i > nums.length-3){
return true;
}
}
}
return false;
}
OR
public boolean unlucky1(int[] nums) {
int len = nums.length;
if(len<2) return false;
if ((nums[0] == 1 && nums[1]==3)||(len>2 && nums[1] == 1 && nums[2]==3)){
return true;
}
if (nums[len-2] == 1 && nums[len-1]==3){
return true;
}
return false;
}

Why won't my while loop if condition work correctly?

My checkWin method returns false until there's a winner in the Connect 4 game by putting 4 "checkers" in a row horizontally, vertically, or diagonally in my board array. Once there's a winner, the checkWin method returns true, the nearest if statement iterates, printing the winner, then terminating the entire loop (if I coded it all correctly). However, when I run the program, the while loop iterates only once, accepts one input for red, states red won, then does the same thing for yellow, then terminates.
What am I missing here?
Below is the relevant code.
Thank you.
public static void main(String[] args) {
char[][] board = new char[6][7];
boolean loop = true;
// loop to alternate players until there's a winner
while (loop) {
printData(board);
red(board);
if (checkWin(board) == true) {
printData(board);
System.out.print("Red wins!");
loop = false;
}
printData(board);
yellow(board);
if (checkWin(board) == true) {
printData(board);
System.out.print("Yellow wins!");
loop = false;
}
}
}
public static void printData(char[][] tbl) {
for (int r = 0; r < tbl.length; r++) {
for (int c = 0; c < tbl[r].length; c++) {
if (tbl[r][c] == 0) {
System.out.print("| ");
} else {
System.out.print("|" + tbl[r][c]);
}
} // end for col loop
System.out.println("|");
} // end for row loop
System.out.println("---------------");
} // end printData method
public static void red(char[][] f) {
System.out.println("Place a red checker at column (0-6)");
Scanner in = new Scanner(System.in);
int c = in.nextInt();
for (int i = 5; i >= 0; i--) {
if (f[i][c] == 0) {
f[i][c] = 'R';
break;
}
}
}
public static void yellow(char[][] f) {
System.out.println("Place a yellow checker at column (0-6)");
Scanner in = new Scanner(System.in);
int c = in.nextInt();
for (int i = 5; i >= 0; i--) {
if (f[i][c] == 0) {
f[i][c] = 'Y';
break;
}
}
}
// Method to check for a winner. Receives 2-D array as parameter. Returns
// boolean value.
public static boolean checkWin(char[][] b) {
// Create four boolean variables, one for each set of rows. Initialize
// all of them to false.
boolean foundRow = false;
boolean foundCol = false;
boolean foundMjrD = false;
boolean foundMinD = false;
// Check to see if four consecutive cells in a row match.
// check rows
for (int r = 0; r <= 5; r++) {
for (int c = 0; c <= 3; c++) {
if (b[r][c] == b[r][c + 1] && b[r][c] == b[r][c + 2] && b[r][c] == b[r][c + 3] && b[r][c] != ' ') {
foundRow = true;
break;
}
}
}
// Check to see if four columns in the same row match
// check columns
for (int r = 0; r <= 2; r++) {
for (int c = 0; c <= 6; c++) {
if (b[r][c] == b[r + 1][c] && b[r][c] == b[r + 2][c] && b[r][c] == b[r + 3][c] && b[r][c] != ' ') {
foundCol = true;
break;
}
}
}
// Check to see if four diagonals match (top left to bottom right)
// check major diagonal
for (int r = 0; r <= 2; r++) {
for (int c = 0; c <= 3; c++) {
if (b[r][c] == b[r + 1][c + 1] && b[r][c] == b[r + 2][c + 2] && b[r][c] == b[r + 3][c + 3]
&& b[r][c] != ' ') {
foundMjrD = true;
break;
}
}
}
// Check to see if four diagonals in the other direction match (top
// right to bottom left)
// check minor diagonal
for (int r = 0; r <= 2; r++) {
for (int c = 3; c <= 6; c++) {
if (b[r][c] == b[r + 1][c - 1] && b[r][c] == b[r + 2][c - 2] && b[r][c] == b[r + 3][c - 3]
&& b[r][c] != ' ') {
foundMinD = true;
break;
}
}
}
// If ONE of the booleans is true, we have a winner.
// checks boolean for a true
if (foundRow || foundCol || foundMjrD || foundMinD)
return true;
else
return false;
} // end checkWin method
By what I've analyzed by debugging your code , you have not set boolean variable to "true" after toggling it to false. After you are coming out of condition make that boolean variable "true" again.
May this help you. Happy Coding
You should take a closer look at this line:
if (b[r][c] == b[r][c + 1] && b[r][c] == b[r][c + 2] && b[r][c] == b[r][c + 3] && b[r][c] != ' ') {
You check for b[r][c] != ' ', but you never put a space in char[][] board, therefore the default value in board[?][?] is 0.

Java maze solving issue

so I've been asked to solve a maze in a recursive java function, but I stumble into an issue that the recursive function doesnt seem to switch the correct path into '*'.
Any help would be appreciated.
public class Maze
{
/**
* This is only an example,
* you can change this to test other cases but don't forget to submit the work with this main.
* #param args
*/
public static void main(String[] args)
{
int M = 4;
int N = 4;
char[][] maze = {{'1','0','0','0'},{'1','1','0','0'},{'0','1','1','1'},{'0','0','0','1'}};
if (findPath(maze, 0,0))
printMaze(maze);
else
System.out.println("No solution");
}
private static void printMaze(char[][] maze)
{
for (int i = 0; i < maze.length; i++)
{
for (int j = 0; j < maze[0].length; j++)
{
System.out.print(maze[i][j] +" ");
}
System.out.println();
}
}
// you should implement this function
private static boolean findPath(char[][] maze, int i, int j)
{
if ((i+1 > maze.length) || (j+1 > maze[i].length))
return false;
else
{
if (maze[i][j] == 1)
{
maze[i][j] = '*';
if (maze[i+1][j] == 1)
{
return findPath(maze, i+1, j);
}
if (maze[i][j+1] == 1)
{
return findPath(maze, i, j+1);
}
}
}
return true;
}
}
You're missing quotes around the 1 at
if (maze[i][j] == 1)
should be
if (maze[i][j] == '1')
The number 1 and the character representing the number 1 are two different things in Java (and in any other statically typed language), so you can't check if they're equal like that.
I doubt that the code will find all paths then though, since you don't seem to be searching left and up at all.
Use this code:
private static boolean findPath(char[][] maze, int i, int j)
{
if (maze[i][j] == 1)
{
maze[i][j] = '*';
if ((i+1 > maze.length && maze[i+1][j] == '1' && findPath(maze, i+1, j))
{
return true;
}
if ((j+1 > maze[i].length) && maze[i][j+1] == '1' && findPath(maze, i, j+1))
{
return true;
}
if (i>=1 && maze[i-1][j] == '1' && findPath(maze, i-1,j)){
return true;
}
if(j>=1 && maze[i][j-1] == '1' && findPath(maze, i,j-1)){
return true;
}
}
return false;
}

Codingbat sameStarChar exercise

I'm having trouble with this codingbat exercise:
Returns true if for every * (star) in the string, if there are chars both immediately before and after the star, they are the same.
sameStarChar("xyyzz") // true
sameStarChar("xyzzz") // false
sameStarChar("xaaz") // true
The right answer is:
public boolean sameStarChar(String str) {
for (int i = 1; i < str.length() - 1; i++) {
if (str.charAt(i) == '*' && str.charAt(i - 1) != str.charAt(i + 1)) {
return false;
}
}
return true;
}
What I wrote is:
public boolean sameStarChar(String str) {
for (int i = 1; i < str.length() - 1; i++) {
if (str.substring(i, i + 1) == "*" && str.substring(i - 1, i) != str.substring(i + 1, i + 2)) {
return false;
}
}
return true;
}
I'm having trouble understanding the substring and charAt methods.
Instructions:
Returns true if for every '*' (star) in the string, if there are chars both immediately before and after the star, they are the same.
sameStarChar("xy*yzz") → true
sameStarChar("xy*zzz") → false
sameStarChar("*xa*az") → true
Pseudocode:
Loop over every character from 1 to length-1. If the character is an asterisk and the character before it is different from the one after, return false. Otherwise if when you reach the end, return true.
Code:
public boolean sameStarChar(String str){
int len = str.length();
for(int x = 1; x < len-1; x++){
if (str.charAt(x) == '*' && str.charAt(x-1) != str.charAt(x+1)){
return false;
}
}
return true;
}
Comments:
It's a linear time O(n) operation.
str.charAt() is easier to read and understand in this case.
Also, your substring solution should be more like
if (str.substring(i, i + 1).equals("*") &&
!str.substring(i - 1, i).equals(str.substring(i + 1, i + 2))){
//etc.
}
Substring returns a string, and to compare the literal sting value you have to use the .equals() method.
Instead, I count the number of '*' and number of pairs that are matched and check if they both are equal and return true.
public boolean sameStarChar(String str) {
int count=0, noOfPairs=0;
for(int i=1; i<str.length()-1;i++){
if(str.charAt(i)=='*') count++;
if(str.charAt(i)=='*' && str.charAt(i+1)==str.charAt(i-1)) noOfPairs++;
}
if(count==noOfPairs) return true;
return false;
}
Another solution to look at...
public boolean sameStarChar(String str) {
if(str.length()==0) return true;
if(str.length()==1 && str.contains("*")) return true;
if(!str.contains("*")) return true;
int i = 0;
boolean result = false;
while(i<str.length()-1){
if(i!=0 && str.charAt(i) == '*' && str.charAt(i-1) == str.charAt(i+1)){
result = true;
}else if(i!=0 && str.charAt(i) == '*' && str.charAt(i-1) != str.charAt(i+1)){
result = false;
}else if(str.charAt(i) == '*'){
result = true;
}
i++;
}
return result;
}
A version which does not iterate over each individual character in the string by using indexOf(int ch, int fromIndex)
public boolean sameStarChar(String str) {
int i=0;
int l=str.length();
for(i=str.indexOf("*",i);i!=-1;i=str.indexOf("*",i+1))
{
if(i==0 || i==l-1) //saves the program from accessing an out of bounds Index
continue;
else
{
if(str.charAt(i-1)!=str.charAt(i+1));
return false;
}
}
return true;
}

Categories

Resources