Searching a 2D Array around a single Position - java

So for a match 3 type game, like candy crush I need to search a 2D array and if the same number is repeated create a match.
For Example, if my 2d array is something like
212031201
012102312
101223200
012131013
010321022
201210101
102023202 <--
012102312 <--
012321022 <--
You notice there are three twos in a line on the bottom right side (arrows pointing). How would I search the array to return the values and create a match. Here is what I am thinking but I'm not sure if even my logic is correct:
public class matchAI
{
Game game = new Game();
public void search() {
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++) {
if (game.board[i][j] == game.Emerald) //game.Board is the Array which is 9x9 filled with numbers 0,1,2. game.Emerald =0
{
//Store value
//Check Around current position for similar numbers
//Add to Score, indicating match, and remove current matched numbers and shift the rest down, like gravity sucks others down.
//Fill top row which would be empty from others shifting
}
}
}
}
}

I think it might be better to keep a 2D array of Tile objects. A Tile class could look like this:
public class Tile {
private int x, y;
private int type;
private int[][] neighbors;
public Tile(int x, int y, int type){
this.x = x;
this.y = y;
this.type = type;
findNeighbors();
}
private void findNeighbors(){
int[] top = new int[] {x, y+1};
int[] right = new int[] {x+1, y};
int[] bottom = new int[] {x, y-1};
int[] left = new int[] {x-1, y};
neighbors = new int[][] {top, right, bottom, left};
}
public int getType() {
return type;
}
public int[] getNeigbor(int side) {
if(side == 0) {
return neighbors[0];
}
//etc
return null;
}
}
Then you can just ask each tile for the position of its neighbors and then check their types. Some checking would be necessary for edge tiles, but I think this should work fairly well.

The elegant way would be to design an iterator that delivers each element around a supplied point.
public static class Around<T> implements Iterable<T> {
// Steps in x to walk around a point.
private static final int[] xInc = {-1, 1, 1, 0, 0, -1, -1, 0};
// Ditto in y.
private static final int[] yInc = {-1, 0, 0, 1, 1, 0, 0, -1};
// The actual array.
final T[][] a;
// The center.
final int cx;
final int cy;
public Around(T[][] a, int cx, int cy) {
// Grab my parameters - the array.
this.a = a;
// And the center we must walk around.
this.cx = cx;
this.cy = cy;
}
#Override
public Iterator<T> iterator() {
// The Iterator.
return new Iterator<T>() {
// Starts at cx,cy
int x = cx;
int y = cy;
// Steps along the inc arrays.
int i = 0;
#Override
public boolean hasNext() {
// Stop when we reach the end of the sequence.
return i < xInc.length;
}
#Override
public T next() {
// Which is next.
T it = null;
do {
// Take the step.
x += xInc[i];
y += yInc[i];
i += 1;
// Is it a good spot? - Not too far down.
if (y >= 0 && y < a.length) {
// There is a row here
if (a[y] != null) {
// Not too far across.
if (x >= 0 && x < a[y].length) {
// Yes! Use that one.
it = a[y][x];
}
}
}
// Keep lookng 'till we find a good one.
} while (hasNext() && it == null);
return it;
}
};
}
}
public void test() {
Integer[][] a = {{0, 1, 2}, {3, 4, 5}, {6, 7, 8}};
for (Integer i : new Around<>(a, 1, 1)) {
System.out.print(i + ",");
}
System.out.println();
for (Integer i : new Around<>(a, 2, 2)) {
System.out.print(i + ",");
}
}

Related

iterating through a 2d array and listing only 1s which are connected

Thank you for the replies...
Hi
i would need a function which takes a 2d array or map with filled with 0 and 1. where 1 represent the walkable ground and 0 is the wall. i need an algorithm which iterates trough the whole array where its walkable... and prints out only the walkable surface and the direction how it walks it trough.. something like in the attached file.
So far i managged to print the walkable surface of an array using flood fill, but didnt managed to print the directions.
Could you help me with that , i am working in Java
Am i on the right direction with flood fill? is it possible to print how the algorithm iterates trough the walkable surface?
I already have the output where the walkable path is changed from 1 to 2 s , but still need the direction printing....
The Code so far
class Solution {
private void dfs(int row, int col,
int[][] ans,
int[][] image,
int newColor, int delRow[], int delCol[],
int iniColor) {
ans[row][col] = newColor;
int n = image.length;
int m = image[0].length;
for(int i = 0;i<4;i++) {
int nrow = row + delRow[i];
int ncol = col + delCol[i];
if(nrow>=0 && nrow<n && ncol>=0 && ncol < m &&
image[nrow][ncol] == iniColor && ans[nrow][ncol] != newColor) {
dfs(nrow, ncol, ans, image, newColor, delRow, delCol, iniColor);
if(nrow == 1) {
System.out.println("Right");
}
if(nrow == -1) {
System.out.println("Left");
}
if(ncol == 1) {
System.out.println("Up");
}
if(ncol == -1) {
System.out.println("Down");
}
}
}
}
public int[][] floodFill(int[][] image, int sr, int sc, int newColor)
{
int iniColor = image[sr][sc];
int[][] ans = image;
int delRow[] = {-1, 0, +1, 0};
int delCol[] = {0, +1, 0, -1};
dfs(sr, sc, ans, image, newColor, delRow, delCol, iniColor);
return ans;
}
public static void main(String[] args)
{
int[][] image = {
{1,1,1,0,1,1},
{0,0,1,0,1,1},
{1,1,1,1,1,0},
{0,0,0,0,0,0},
{1,1,1,0,1,1}
};
Solution obj = new Solution();
int[][] ans = obj.floodFill(image, 0, 0, 2);
for(int i = 0; i < ans.length; i++){
for(int j = 0; j < ans[i].length; j++)
System.out.print(ans[i][j] + " ");
System.out.println();
}
}
}

Knight's tour in Java with rocks

I am working on the following problem:
Write a method that, given a chessboard with one knight, rocks on some of the squares, and a target position, indicates whether or not the knight can reach the target without landing on any rocks, and if so, the smallest number of moves needed by the knight to reach the target. The method should return the minimum number of moves needed to do so; otherwise, the method should return the value -1. (If the initial position has a rock on it, the method should return -1; likewise, if the target position has a rock on it, the method should return -1.)
You can see the code I've implemented so far below. My approach to rocks is to change the "coordinates" on the chessboard that have rocks as visited, so the knight can't revisit them, hence blocking his path(?).
My program compiles but doesn't return either minimum moves or -1. Any tips/different approaches to the problem are much appreciated. Thanks!!
PS: I'm ridiculously new to Java so apologies in advance for the messy code :)
import java.util.*;
public class Knight {
public static int numMoves( int dim, int xstart, int ystart, int xtarget,
int ytarget, int[] xrock, int[] yrock )
{
int result = -1;
List<Integer> knightPos = new ArrayList<>(Arrays.asList(xstart, ystart));
int [] targetPos = {xtarget, ytarget};
int dis = 0;
// x and y direction, where a knight can move
int[] dx = { -2, -1, 1, 2, -2, -1, 1, 2 };
int[] dy = { -1, -2, -2, -1, 1, 2, 2, 1 };
// queue for storing states of knight in board
Vector<cell> q = new Vector<>();
// push starting position of knight with 0 distance
q.add(new cell(knightPos.get(xstart), knightPos.get(ystart), dis));
cell t;
int x, y;
boolean[][] visit = new boolean[dim + 1][dim + 1];
// make all cell unvisited
for (int i = 1; i <= dim; i++) {
for (int j = 1; j <= dim; j++) {
visit[i][j] = false;
}
}
// visit starting state
visit[knightPos.set(0,xstart)][knightPos.set(1,ystart)] = true;
// visit rock squares
for (int i = 0; i < xrock.length;) {
for (int j = 0; j < yrock.length; ++i, ++j) {
visit[knightPos.get(i)][knightPos.get(j)] = true;
}
}
// loop until we have one element in queue
while (!q.isEmpty()) {
t = q.firstElement();
q.remove(0);
// if current cell is equal to target cell,
// return its distance
if (t.x == targetPos[0] && t.y == targetPos[1])
return t.dis;
// loop for all reachable states
for (int i = 0; i < 8; i++) {
x = t.x + dx[i];
y = t.y + dy[i];
// If reachable state is not yet visited and
// inside board, push that state into queue
if (isInside(x, y, dim) && !visit[x][y]) {
visit[x][y] = true;
q.add(new cell(x, y,dis + 1));
}
}
}
return result;
}
public static boolean isInside (int x, int y, int dim)
{
return x >= 0 && x <= dim && y >= 0 && y <= dim;
}
static class cell {
int x, y;
int dis;
public cell(int x, int y, int dis) {
this.x = x;
this.y = y;
this.dis = dis;
}
}
public static void main( String[] args )
{
}
}

Setting a member variable for one instance of a class overwrites the same member variable for other class instances

So I am making a simple battle ships game (I am fairly new to java...) and I am getting an unexpected result when assigning the locations of 'ships' to a virtual grid of 7x7. I'll start with showing the test code and the output from that code:
Ship[] ships = new Ship[2];
for (int i = 0; i < ships.length; i++) {
ships[i] = new Ship();
ships[i].setLocationCells(ShipLocations.createLocations());
System.out.println(Arrays.deepToString(ships[i].getLocationCells()));
}
for (int i = 0; i < ships.length; i++) {
System.out.println(Arrays.deepToString(ships[i].getLocationCells()));
}
System.out.println(Arrays.deepToString(ShipLocations.getUsedLocations()));
So I am just initializing an array that holds two Ship objects. I loop through and create those objects. ShipLocations.createCells() returns a 3x2 2D array of random unique locations. Set and get methods are pretty standard. The output of this code is this:
[[1, 3], [1, 4], [1, 5]]
[[4, 5], [5, 5], [6, 5]]
[[4, 5], [5, 5], [6, 5]]
[[4, 5], [5, 5], [6, 5]]
[[1, 3], [1, 4], [1, 5], [4, 5], [5, 5], [6, 5]}
So it appears from this that when it is initially set, the positions are indeed unique but in the second for loop where I go back to check the locations, it appears that both object's location cells have been set to the last values generated from ShipLocations.createLocationCells(). The last print is showing all the locations that have created and stored by ShipLocations (as you can see those values are unaffected and still unique). So what is going on here? Why is the last call to setLocationCells() resetting the member variable for both Ship() instances? I am wondering if there is a reference pointer problem here that I am just missing somehow... Do the ship reference variables point to the same object and that's what is happening? Here is the Ship class if that helps with any clarification questions:
import java.util.Arrays;
public class Ship {
private int len = 3;
private int[][] locationCells = new int[3][2];
private int numOfHits = 0;
public String check(int[] g) {
// compare user guess to location cell
for (int i = 0; i < locationCells.length; i++) {
//look for hit, if guess is a location...
if (locationCells[i][0] == g[0] && locationCells[i][1] == g[1]) {
// increase num of hits
numOfHits++;
// shrink locationsCells and remove the hit location
shrinkLocations(g);
if (locationCells.length == 0) {
return "kill";
}
else {
return "hit";
}
}
}
return "miss";
}
public void shrinkLocations(int[] guess) {
int[][] temp = new int[locationCells.length - 1][2];
int currentPos = 0;
for (int i = 0; i < locationCells.length; i++) {
if (!(locationCells[i][0] == guess[0] && locationCells[i][1] == guess[1])) {
temp[currentPos] = locationCells[i];
currentPos++;
}
}
setLocationCells(temp);
}
public void setLocationCells(int[][] locations) {
this.locationCells = locations;
}
public int[][] getLocationCells() {
return this.locationCells;
}
public void setLen(int len) {
this.len = len;
}
public int getLen() {
return len;
}
public int getNumOfHits() {
return numOfHits;
}
}
Here is the ShipLocations class (by request):
mport java.util.Random;
public class ShipLocations {
// array that holds the nine total ship locations
private static int len = 3;
private static int[][] usedLocations = new int[9][2];
private static int[][] shipLocations = new int[len][2];
public static int[][] createLocations(){
// need to know if you are going to position ship up or down.
Random randint = new Random();
// control boolean for do-while loop below
boolean locationsHaveBeenUsed = false;
boolean placementIsValid = false;
int xLoc;
int yLoc;
int direction = randint.nextInt(2);
// generate locations until the initial location isnt already used
do {
// x location starts at 1 and goes to a point where it will still fit on the board
xLoc = randint.nextInt(8 - len) + 1;
// y location starts at 1 and goes to a point where it will still fit on the board
yLoc = randint.nextInt(8 - len) + 1;
locationsHaveBeenUsed = hasBeenUsed(xLoc, yLoc);
//generate new direction and try again.
direction = randint.nextInt(2);
placementIsValid = validPlacement(xLoc, yLoc, direction);
// only place if the locations have not been NOT been used
if (placementIsValid && !locationsHaveBeenUsed) {
//make a call to place at those locations.
placeShipLocations(xLoc, yLoc, direction);
}
// stop once both the locations haven't been used and the placement is not valid
} while (locationsHaveBeenUsed || !placementIsValid);
// current shipLocations array has been altered, return.
return shipLocations;
}
public static boolean hasBeenUsed(int xLoc, int yLoc) {
for (int[] loc : usedLocations) {
// if the randomly generated location has already been used, generate again.
if (loc[0] == xLoc && loc[1] == yLoc) {
return true;
}
}
// if not found in usedLocaations return false
return false;
}
public static void placeInNonEmpty(int xLoc, int yLoc) {
// add the location to used locations in the slot that is first available (non-double zeros)
for (int j = 0; j < usedLocations.length; j++) {
if (usedLocations[j][0] == 0 && usedLocations[j][1] == 0) {
usedLocations[j][0] = xLoc;
usedLocations[j][1] = yLoc;
break;
}
}
}
public static void placeShipLocations(int x, int y, int direction) {
for (int i = 0; i < len; i++) {
// place in UsedLocations array
placeInNonEmpty(x, y);
// place in current shipLocations
shipLocations[i][0] = x;
shipLocations[i][1] = y;
if (direction == 1) {
// moving location up and down
y++;
}
else {
// moving location left and right
x++;
}
}
}
public static boolean validPlacement(int x, int y, int direction) {
for (int i = 1; i < len; i++) {
if (direction == 1) {
// moving location up and down
y++;
}
else {
// moving location left and right
x++;
}
for (int[] loc : usedLocations) {
// check through each location in usedLocations
if (loc[0] == x && loc[1] == y) {
// moving in that direction is not compatible return false and try again
return false;
}
}
}
// if it makes it through that checking minefield return true.
return true;
}
public static int[][] getUsedLocations() {
return usedLocations;
}
}

Exception in thread "main" java.lang.IllegalArgumentException: Parameter N must be positive at StdRandom.uniform(StdRandom.java:119)

I am new to this website so correct me if there is anything wrong with my question. I keep receiving this error and I am not entirely sure what is wrong with my program:
Exception in thread "main" java.lang.IllegalArgumentException: Parameter N must be positive
at StdRandom.uniform(StdRandom.java:119)
at Maze.chooseRandomlyFrom(Maze.java:52)
at Maze.expandMaze(Maze.java:136)
at Maze.main(Maze.java:193)**
I ran the JUnit test in my IDE (eclipse) however I could not trace where the error is coming from. Any help or guidance is greatly appreciated and thank you for taking the time to check out the code. Here is what I am working with. I included comments for each method as clearly as I could.
public class Maze {
public static final int EAST = 1;
public static final int NORTH = 0;
public static final int[][] OFFSETS = { { 0, 1 }, { 1, 0 }, { 0, -1 }, { -1, 0 } };
public static final int SOUTH = 2;
public static final int WEST = 3;
//Purpose: Modifies passage to contain a one-way passage from location a to location
//b. Assumes these two locations (arrays of two numbers) are adjacent.
//Parameters: boolean[][][] passages, int[] a, int[] b
//Return: N/A
public static void addPassage(boolean[][][] passages, int[] a, int[] b)
{
int ax = a[0];
int ay = a[1];
int bx = b[0];
int by = b[1];
if (by == ay + 1) {
passages[ax][ay][0] = true;
} else if (bx == ax + 1) {
passages[ax][ay][1] = true;
} else if (by == ay - 1) {
passages[ax][ay][2] = true;
} else {
passages[ax][ay][3] = true;
}
}
//Purpose: Gets array of pairs containing start and all locations in the list.
//Parameters: int[] start, int[][] list
//Return: Returns a new array of pairs containing start followed by all of the locations in list.
public static int[][] addToFront(int[] start, int[][] list)
{
int[][] path = new int[list.length + 1][];
path[0] = start;
for (int i = 1; i < path.length; i++) {
path[i] = list[(i - 1)];
}
return path;
}
//Purpose: Gets random one from the first element of the list
//Parameters: int[][] list, int n
//Return: Returns a random one of the first n elements of list.
public static int[] chooseRandomlyFrom(int[][] list, int n)
{
return list[StdRandom.uniform(n)];
}
//Purpose: Gets pair and compares to first number as one of the first n element
//Parameters: int[] pair, int[][] list, int n
//Return: Returns true if pair, assumed to be an array of two numbers, has the same
//numbers as one of the first n elements of list.
public static boolean contains(int[] pair, int[][] list, int n)
{
for (int i = 0; i < n; i++) {
if ((pair[0] == list[i][0]) && (pair[1] == list[i][1])) {
return true;
}
}
return false;
}
//Purpose: Will draw the maze
//Parameters: boolean[][][] passages
//Return: N/A
public static void drawMaze(boolean[][][] passages)
{
StdDraw.clear(StdDraw.PINK);
StdDraw.setPenColor(StdDraw.WHITE);
int width = passages.length;
StdDraw.setPenRadius(0.75 / width);
// Draw passages
for (int x = 0; x < width; x++) {
for (int y = 0; y < width; y++) {
if (passages[x][y][NORTH] || (y + 1 < width && passages[x][y + 1][SOUTH])) {
StdDraw.line(x, y, x, y + 1);
}
if (passages[x][y][EAST] || (x + 1 < width && passages[x + 1][y][WEST])) {
StdDraw.line(x, y, x + 1, y);
}
}
}
// Draw entrance and exit
StdDraw.line(0, 0, -1, 0);
StdDraw.line(width - 1, width - 1, width, width - 1);
StdDraw.show(0);
}
//Purpose: Will draw the maze solution
//Parameters: int[][] path, int width
//Return: N/A
public static void drawSolution(int[][] path, int width)
{
StdDraw.setPenColor(); // Black by default
StdDraw.setPenRadius();
StdDraw.line(0, 0, -1, 0);
StdDraw.line(width - 1, width - 1, width, width - 1);
for (int i = 0; i < path.length - 1; i++) {
StdDraw.line(path[i][0], path[i][1], path[i + 1][0], path[i + 1][1]);
}
StdDraw.show(0);
}
//Purpose: Checks if here's neighbor in direction (called there) is in unexplored. If so, adds a passage from here
//to there and returns there. If not,returns null.
//Parameters: boolean[][][] passages, int[][] unexplored, int n, int[] here, int direction otherwise.
public static int[] expandLocation(boolean[][][] passages, int[][] unexplored, int n, int[] here, int direction)
{
int[] there = new int[2];
here[0] += OFFSETS[direction][0];
here[1] += OFFSETS[direction][1];
if (contains(there, unexplored, n))
{
addPassage(passages, here, there);
return there;
}
return null;
}
//Purpose: Chooses "here" to be either lastExploredLocation (if it is not null) or a random location in
//frontier. If possible, adds a passage from "here" to a location "there" in unexplored, then moves "there" from unexplored to
//frontier. If not, moves "here" from frontier to done.
//Parameters: boolean[][][] passages, int[][] done, int[][] frontier, int[][] unexplored, int[] counts, int[] lastExploredLocation
//Return: N/A
public static int[] expandMaze(boolean[][][] passages, int[][] done, int[][] frontier, int[][] unexplored, int[] counts, int[] lastExploredLocation)
{
int[] here;
if (lastExploredLocation == null) {
here = chooseRandomlyFrom(frontier, counts[1]);
} else {
here = lastExploredLocation;
}
int direction = StdRandom.uniform(4);
for (int i = 0; i < 4; i++)
{
int[] there = expandLocation(passages, unexplored, counts[2], here, direction);
if (there != null)
{
frontier[counts[1]] = there;
counts[1] += 1;
remove(there, unexplored, counts[2]);
counts[2] -= 1;
return there;
}
direction = (direction + 1) % 4;
}
done[counts[0]] = here;
counts[0] += 1;
remove(here, frontier, counts[1]);
counts[1] -= 1;
return null;
}
//Purpose: Draws then solves maze
//Parameters: String[] args
//Return: N/A
public static void main(String[] args)
{
int width = 20;
StdDraw.setXscale(-0.5, width - 0.5);
StdDraw.setYscale(-0.5, width - 0.5);
StdDraw.show(0);
boolean[][][] passages = new boolean[width][width][4];
// Initially, no locations are done
int[][] done = new int[width * width][];
// The frontier only contains {0, 0}
int[][] frontier = new int[width * width][];
frontier[0] = new int[] { 0, 0 };
// All other locations are in unexplored
int[][] unexplored = new int[width * width][];
// Number of nodes done, on the frontier, and unexplored
int[] counts = { 0, 1, width * width - 1 };
int i = 0;
for (int x = 0; x < width; x++) {
for (int y = 0; y < width; y++) {
if (x != 0 || y != 0) {
unexplored[i] = new int[] { x, y };
i++;
}
}
}
// As long as there are unexplored locations, expand the maze
int[] lastExploredLocation = null;
while (counts[2] > 0) {
lastExploredLocation = expandMaze(passages, done, frontier, unexplored, counts, lastExploredLocation);
drawMaze(passages);
StdDraw.show(25);
}
// Solve the maze
int[][] solution = solve(passages, new int[] { 0, 0 }, new int[] { width - 1, width - 1 });
drawSolution(solution, width);
}
//Purpose: Modifies list so that pair is replaced with the (n - 1)th element of list. Assumes pair is an
//array of two numbers that appears somewhere in list. Thus, when this method is done, the first n - 1 element of list are
//the same as the first n elements of the old version, but with pair removed and with the order of elements potentially different.
//Parameters: int[] pair, int[][] list, int n
//Return: N/A
public static void remove(int[] pair, int[][] list, int n)
{
for (int i = 0; i < n; i++) {
if ((pair[0] == list[i][0]) && (pair[1] == list[i][1]))
{
list[i] = list[(n - 1)];
return;
}
}
}
//Purpose: Gets a return path from start to finish
//Parameters: boolean[][][] passages, int[] start, int[] goal
//Return: Returns a path (sequence of locations) leading from start to goal in passages or null if there is no such path.
public static int[][] solve(boolean[][][] passages, int[] start, int[] goal) {
if ((start[0] == goal[0]) && (start[1] == goal[1])) {
return new int[][] { goal };
}
for (int d = 0; d < 4; d++) {
if (passages[start[0]][start[1]][d] != false)
{
int[] next = { start[0] + OFFSETS[d][0], start[1] + OFFSETS[d][1] };
int[][] restOfPath = solve(passages, next, goal);
if (restOfPath != null) {
return addToFront(start, restOfPath);
}
}
}
return null;
}
}
When you pass the argument 'n' to
StdRandom.uniform() at Maze.chooseRandomlyFrom(Maze.java:52) the argument you are passing is negative. According to the error message, the parameter must be positive. This could be because during expandMaze, you are assigning counts[1] to be one less than its current value (counts[1] -= 1;), which will eventually result in a negative number. It would appear that the method is called over and over as long as counts[2] > 0, which in some cases must be the case for enough iterations such as counts[1] becomes a negative number.
Perhaps before calling this StdRandom.uniform() method, you should take the absolute value of counts[1] to ensure it is always positive. Math.abs(counts[1]) should do the trick.

Arrays for Maze Algorithm not Storing Proper Values

I have everything down in my maze solver, except for the fact that the wasHere array is storing the solution (which is supposed to be stored by the correctPath array). It is also missing marking the end square of the maze. All the wasHere array is supposed to store are the spots that the program has gone to in the maze. The correctPath array has all false values, which is totally unexpected. I am using the recursive method mentioned in Wikipedia: https://en.wikipedia.org/wiki/Maze_solving_algorithm
This is my Maze Solver:
private static int[][] maze = {{2, 2, 2, 2, 1, 2, 2},
{2, 2, 2, 2, 1, 2, 2},
{2, 2, 2, 2, 1, 2, 2},
{2, 1, 1, 1, 1, 1, 1}}; // The maze
private static boolean[][] wasHere = new boolean[4][7];
private static boolean[][] correctPath = new boolean[4][7]; // Solution
private static int startX = 4;
private static int startY = 0;
private static int endX = 1;
private static int endY = 3;
public static void main(String[] args) {
System.out.println("Maze: ");
printMaze(maze);
solveMaze();
boolean b = recursiveSolve(startX, startY); // Whether or not there is a solution to the maze
}
public static void solveMaze()
{
for (int row = 0; row < maze.length; row++)
{
// Sets boolean arrays to false
for (int col = 0; col < maze[row].length; col++)
{
wasHere[row][col] = false;
correctPath[row][col] = false;
}
}
}
public static void printMaze(int[][] array)
{
for (int row = 0; row < array.length; row++)
{
for (int col = 0; col < array[row].length; col++)
{
System.out.print(array[row][col]);
if (col == array[row].length - 1)
{
System.out.print("\n");
}
}
}
System.out.print("\n");
}
public static void printPath(boolean[][] array)
{
for (int row = 0; row < array.length; row++)
{
for (int col = 0; col < array[row].length; col++)
{
if (array[row][col] == true)
{
System.out.print("1");
}
else
{
System.out.print("2");
}
if (col == array[row].length - 1)
{
System.out.print("\n");
}
}
}
}
public static boolean recursiveSolve(int x, int y)
{
if (x == endX && y == endY) // Reach end
{
System.out.println("The maze is solvable.");
printPath(wasHere);
return true;
}
if (maze[y][x] == 2 || wasHere[y][x] == true) // Hit a dead end or end up in same place (no solution)
{
return false;
}
wasHere[y][x] = true;
if (x != 0) // On left edge or not
{
if (recursiveSolve(x - 1, y))
{
correctPath[y][x] = true;
return true;
}
}
if (x != maze[0].length - 1) // On right edge or not
{
if (recursiveSolve(x + 1, y))
{
correctPath[y][x] = true;
return true;
}
}
if (y != 0) // On top edge or not
{
if (recursiveSolve(x, y - 1))
{
correctPath[y][x] = true;
return true;
}
}
if (y != maze.length - 1) // On bottom edge or not
{
if (recursiveSolve(x, y + 1))
{
correctPath[y][x] = true;
return true;
}
}
System.out.println("The maze is not solvable.");
return false;
}
Your maze solver is working correctly. The problem is that you were probably printing the values of the correctPath array before your recursive method had finished writing to it.
I assume that where you had the following lines inside the recursiveSolve(int x, int y) method:
System.out.println("The maze is solvable.");
printPath(wasHere);
... at some point, you tried to run it using the correctPath variable instead, right? Something like this?
System.out.println("The maze is solvable.");
printPath(correctPath);
But that is too soon. The correctPath array values are set after the recursive calls start returning from the end of the maze.
Instead, try moving the printPath call after the top level call to the recursiveSolve method inside your main(). Like this:
public static void main(String[] args) {
System.out.println("Maze: ");
printMaze(maze);
solveMaze();
boolean b = recursiveSolve(startX, startY); // Whether or not there is a solution to the maze
// Put this here! It will work as expected.
System.out.println();
printPath(correctPath);
}
If this doesn't quite make sense to you, then it probably means that you haven't quite grasped how recursion works. Use a debugger to step through your program, as you should have done in the first place, and things should become clearer.

Categories

Resources