5

For my C++ assignment, I'm basically trying to search through a chunk of text in a text file (that's streamed to my vector vec) beginning at the second top character on the left. It's for a text maze, where my program in the end is supposed to print out the characters for a path through it.

An example of a maze would be like:

###############
Sbcde####efebyj
####hijk#m#####
#######lmi#####
###############
###############
###############
###############
###############
###############
###############
###############
###############
###############
###############

Where '#' is an unwalkable wall and you always begin on the left at the second top character. Alphabetical characters represent walkable squares. Exit(s) are ALWAYS on the right. The maze is always a 15x15 size in a maze.text file. Alphabetical characters repeat within the same maze, but not directly beside each other.

What I'm trying to do here is: if a square next to the current one has an alphabetical character, add it to the vector vec, and repeat this process until I get to the end of the maze. Eventually I am supposed to make this more complicated by printing to the screen multiple paths that exist in some mazes.

So far I have this for the algorithm itself, which I know is wrong:

    void pathcheck()
{
    if (isalpha(vec.at(x)) && !(find(visited.begin(), visited.end(), (vec.at(x))) != visited.end()) )
    {
        path.push_back(vec.at(x));
        visited.push_back(vec.at(x));
        pathcheck(vec.at(x++));
        pathcheck(vec.at(x--));
        pathcheck(vec.at(x + 16));
        pathcheck(vec.at(x - 16));
    }
}

visited is my vector keeping track of the visited squares.

How would I update this so it actually works, and eventually so I can manage more than one path (i.e. if there were 2 paths, the program would print to the screen both of them)? I recall being told that I may need another vector/array that keeps track of squares that I've already visited/checked, but then how would I implement that here exactly?

Mike
  • 47,263
  • 29
  • 113
  • 177
forthewinwin
  • 4,455
  • 4
  • 19
  • 17
  • You'll need to remember where you've been so you don't check that again. Otherwise you would be constantly going one step forward one step back, and no one goes too far like that... – K-ballo May 26 '12 at 02:53
  • Updated. But I know my vec.at in the recursive calls is wrong... what am I supposed to put? – forthewinwin May 26 '12 at 03:08
  • Are you also checking that you don't step outside the 15x15 maze area? – K-ballo May 26 '12 at 03:10
  • 1
    I had offered an answer involving researching DFS and BFS but rereading your post and reading these comments I see that you're more concerned with implmentation issues than how to find a solution. – acattle May 26 '12 at 03:12
  • I saw the comment earlier about DFS and BFS and read the wiki pages, but I'm not sure how I'd put it into code. – forthewinwin May 26 '12 at 04:41
  • As you probably already saw, I reinstated my answer as well as I've tried to update it to talk more about implementation considerations. I also, I noticed that the alphabetic characters in your maze are not unique, so I added a bit to deal with that. – acattle May 26 '12 at 09:53

1 Answers1

3

You're on the right track. When it comes to mazes, the typical method of solving is through either a depth-first search (the most efficient solution for finding some path) or breadth-first search (less efficient, but is guarenteed to find the optimal path). Since you seem to want to do an exhaustive search, these choices are basically interchangeable. I suggest you read up on them:

http://en.wikipedia.org/wiki/Depth-first_search

http://en.wikipedia.org/wiki/Breadth-first_search

Basically, you will need to parse your maze and represent it as a graph (where each non "#" is a node and each link is a walkable path). Then, you keep a list of partial paths (i.e. a list of nodes, in the order you visited them, for example, [S, b, c] is the partial path starting from S and ending at c). The main idea of DFS and BFS is that you have a list of partial paths, and one by one you remove items from the list, generate all possible partial paths leading from that partial path, then place them in the list and repeat. The main difference between DFS and BFS is that DFS implements this list as a stack (i.e. new items have greatest priority) and BFS uses a queue (i.e. new items have lowest priority).

So, for your maze using DFS it would work like this:

  1. Initial node is S, so your initial path is just [S]. Push [S] into your stack ([ [S] ]).
  2. Pop the first item (in this case, [S]).
  3. Make a list of all possible nodes you can reach in 1 move from the current node (in your case, just b).
  4. For each node from step 3, remove any nodes that are part of your current partial path. This will prevent loops. (i.e. for partial path [S, b], from b we can travel to c and to S, but S is already part of our partial path so returning is pointless)
  5. If one of the nodes from step 4 is the goal node, add it to your partial path to create a completed path. Print the path.
  6. For each node from step 4 that IS NOT the goal node, generate a new partial path and push it into the stack (i.e. for [S], we generate [S, b] and push it into the stack, which now should look like [ [S, b] ])
  7. Repeat steps 2 through 6 until the stack is empty, meaning you have traversed every possible path from the starting node.

NOTE: in your example there are duplicate letters (for example, three "e"s). For your case, maybe make a simple "Node" class that includes a variable to hold the letter. That way each "e" will have it's own instance and the pointers will be different values letting you easily tell them apart. I don't know C++ exactly, but in pseudo code:

class Node:
    method Constructor(label):
        myLabel = label
        links = list()

    method addLink(node):
        links.add(node)

You could read every character in the file and if it is not "#", create a new instance of Node for that character and add all the adjacent nodes.

EDIT: I've spent the last 3 years as a Python developer and I've gotten a bit spoiled. Look at the following code.

s = "foo"
s == "foo"

In Python, that assertion is true. "==" in Python compares the string's content. What I forgot from my days as a Java developer is that in many languages "==" compares the string's pointers. That's why in many languages like Java and C++ the assertion is false because the strings point to different parts of memory.

My point is that because this assertion is not true, you COULD forgo making a Node class and just compare the characters (using ==, NOT using strcmp()!) BUT this code could be a bit confusing to read and must be documented.

Overall, I'd use some sort of Node class just because it's fairly simple to implement and results in more readable code AND only requires parsing your maze once!

Good Luck

acattle
  • 3,073
  • 1
  • 16
  • 21