4

I've gotten my maze solver program to work but it seems to be including back tracked spaces (places it went to and hit a wall so it had to turn around) in the final solution path that it outputs. Here is an example:

enter image description here

How can I prevent this in my current implementation below:

int dir = 4;

bool visited[Max_Maze][Max_Maze][dir];


for (row = 0; row < size; ++ row)
{
  for (col = 0; col < size; ++ col)
  {
    for (dir = 0; dir < 4; ++ dir)
    {
      visited[row][col][dir]=false;
    }
  }
}

bool notSolved = true;
int path = 0;
row = 0;
col = 0;

rowStack.push(row);
colStack.push(col);

while (notSolved)
{

  //from perspective of person looking at maze on screen
  if (((row-1)>=0)&&(maze[row - 1][col] == 0)&&(visited[row][col][0]==false))
  {
    // if that space is not out of bounds and if you can go up
    // and you have not gone in that direction yet, go up
    visited[row][col][0] = true; 
    row--;
    rowStack.push(row);
    colStack.push(col);
    path++;
  }
  else if (((col+1)<size)&&(maze[row][col + 1] == 0)&&(visited[row][col][1]==false))
  {
    //else if you can go right etc., go right
    visited[row][col][1] = true;
    col++;
    rowStack.push(row);
    colStack.push(col);
    path++;
  }
  else if (((row+1)<size)&&(maze[row + 1][col] == 0)&&(visited[row][col][2]==false))
  {
    //else if you can go down etc., go down
    visited[row][col][2] = true;
    row++;
    rowStack.push(row);
    colStack.push(col);
    path++;
  }
  else if (((col-1)>=0)&&(maze[row][col - 1] == 0)&&(visited[row][col][3]==false))
  {
    //else if you can go left etc., go left
    visited[row][col][3] = true;
    col--;
    rowStack.push(row);
    colStack.push(col);
    path++;
  }
  else
  {
    //if stuck
    if (path == 0)
    {
      cout << "No Solution Path" << endl;
      notSolved = false;
    }
    else
    {
      rowStack.pop();
      colStack.pop();
      row = rowStack.top();
      col = colStack.top();
      path--;
    }
  }

  if((maze[row][col] == 0) && (row == (size - 1) && col == (size - 1)))
  {
    //if we reached an exit
    cout << "Solution Path:(in reverse)" << endl;
    for (int i = 0; i <= path; i++)
    {
      cout << "row:" << rowStack.top() << " col:" << colStack.top() << endl;
      rowStack.pop();
      colStack.pop();
    }
    notSolved = false;
  }
}

Simple fix or total restructuring needed?

Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
darko
  • 2,438
  • 8
  • 42
  • 54

2 Answers2

3

As the solver goes right into that dead end, it records that it has "visited right from (R, C)", because your visited array is three dimensional. But it never records that it has "visited left from (R, C + 1)". So it thinks it's fine to move to the same position twice, so long as it doesn't make the exact same move twice (which it doesn't, as it's moving left when it backtracks, not right).

It looks like it will work fine as is if you change visited to be a 2-dimensional array and only record positions, not moves. Then every square you've visited before blocks further movement, but that's okay because if the correct solution requires going back to that square you'll eventually hit the else case enough to pop back to it, and from there three must be a never-visited square to explore.

Ben
  • 68,572
  • 20
  • 126
  • 174
  • Ok, I think I implemented that change correctly: http://pastebin.com/67pdjtxT Still has the same issue though: http://imgur.com/3h9GZ This time it only included one back tracked space though? – darko Dec 01 '11 at 03:50
  • @mwmnj I don't have the time to read through your code in detail (and it's your homework, not mine), but I can think of a number of things that could go wrong. Make sure you record the starting square as visited. If you record a square visited just before leaving it, make sure you also do this in the pop case. If you record a square visited just before you enter it, make sure you're recording the square you're about to go to, not the square you're currently in. If none of those things are wrong, step through your code to find out where it backtracks when it should pop, and find out why. – Ben Dec 01 '11 at 04:54
  • Forgot to mark the first square visited, thanks for the help! – darko Dec 01 '11 at 13:24
0

Without commenting on your specific solution, you might consider redoing as a standard depth first search algorithm, which I think you will agree is somewhat more clear:

boolean dfs (State s) {
    if (end_state(s)) {
        return true;
    }

    vector<option_t> options = generate_moves(s);
    for (vector<option_t>::iterator it = options.begin();
         it != options.end(); it++) {
        make_move(s, it);
        boolean found = dfs(s);
        if (found) {
            cout << s << endl;
        }
        undo_move(s, it);
        if (found) return true;
    }
    return false;
}

As you can see, this will work as long as you can create:

  1. some class State that holds your current maze state
  2. end_state function that knows when State is at a solution
  3. generate_moves function that can find all options for current State
  4. make_move that can apply a move against your state
  5. undo_move that can undo a move against state
  6. you define option_t such that it represents a move option
  7. define operator<< for State

I can tell you that certainly the solution I give you does not have problems with printing backtracked spaces (should be clear also from the code).

Kevin
  • 24,871
  • 19
  • 102
  • 158