Data Structure and algorithm 4: Maze path)

Source: Internet
Author: User

Data Structure and algorithm 4: Maze path)
Data Structure and algorithm 4: Maze path)

Preface

This section describes two typical maze algorithms in the textbook [1] [2. Pay attention to the application of stack. If you have any suggestions for improvement, please help me.



1. Intuitive feeling of maze Problems

The following is an intuitive view of the Maze problem. The introduction is only to help you understand the problem. OpenGL and other plotting contents are not involved here.

Moderate brown indicates channel blocking, White indicates available channel, red indicates start position, Green indicates current position, and yellow indicates exit.

(It is drawn using C ++ and OpenGL. Currently, it is a 2D version. If the 3D version is free, add it)

Maze 1:



Maze 2:


2. Maze Algorithm 2.1 The Maze initialization can be expressed in a two-dimensional character array, regardless of whether the maze is 2D or 3D to express the current position, channel, or exit entry.

A two-dimensional character array is used to express the maze map. This idea comes from [1]. I think it is very important and reflects the essence of the maze.

For example, in maze 1, the map file is as follows, which is explained below:

111111111111000001000110100010101e010000010110111110101101010001011000101000111111010001101m10100011000001000111111111111

For example, in maze 2, the map file is as follows:

11111111111m0100010110010001011000011001101110000110001000011010001001101110110111000000e11111111111

In the following implementation process, the method I used is to define an array to store each Cell, and each Cell contains characters. The characters are defined as follows:

'1': Indicates channel blocking, unavailable

'0': indicates the available channel

'M': Start Point (originally meant to be a mouse)

'E': Exit

'.': Indicates the dot that has been accessed.

The infrastructure is defined as follows:

class Pos2D{public:Pos2D(){row = col = 0;}    Pos2D(int r,int c){row = r,col = c;}bool operator != (const Pos2D& pos){return !(*this == pos);}bool operator == (const Pos2D& pos){return this->row == pos.row && this->col == pos.col;}    public:const static Pos2D NotAvailablePos;    int row,col;};struct Cell{Pos2D pos;char content;// 'm' startpos '0' represents passage,'1' blocked,'e' exit,'.' visitedint  triedTime;};

Maze represents the Maze class and contains the data structure:

class Maze{//for convenient we set it to publicpublic:static const char ENTRY_CONTENT = 'm',EXIT_CONTENT='e',BLOCKED_CONTENT='1',PASSAGE_CONTENT='0',VISITED_CONTENT='.';Cell *cellArray;  //array to store cellsint rowCnt,colCnt;// map file row and col countPos2D startPos,exitPos; };

CellArray stores all cell nodes. rowCnt and colCnt represent the number of rows and columns in the map file.

2.2 algorithm 1
Textbook [1] provides the basic idea of algorithm 1:

First, set the entry to the current position. Then, start from the current position and test the first available next unit in a fixed order (for example, the upper and lower order on the right, then, set the next unit as the current unit and repeat the test until an exit is encountered. If it is found during the test, no matter which position on the left or right of the current node cannot reach the next available position, return to the previous node of the current node, set the previous node as the current unit, and continue the test. And so on.

Note the following points:

1) Each walk-through unit must be marked as already passed, and cannot be repeated later.

Because there are two types of elements that you walk through, the first one can find the exit, then you may come back and may fall into a loop of the same path,

For example, A-> B-> C-> A-> B-> C. We need to eliminate this duplicate path.

Second, the exit cannot be found. Since the exit cannot be found after the first visit, why should we continue the second visit?

Therefore, the units that pass through cannot be repeated.

2) Select an available unit from the four directions of the cell each time. To maintain the count of the four directions, the direction of the last attempt cannot be repeated, the anti-Evidence method can be described.

3) The program exit problem is either to find the path after the test, and the whole path is saved in the stack; or the path is not found, so the stack is empty because you keep rolling back, at the end of the process, there is no path at the starting point. Therefore, the stack is empty after stack rollback.

Note that, The actual implementation of the Maze judgment algorithm code must be listed below simple; in order to give the path information, I added multiple auxiliary code in the code.

An algorithm is implemented as follows:

Find the first available unit in four directions:

//find first avaliable posPos2D Maze::getFirstAvailablePos(Pos2D curPos){   int row = curPos.row,col = curPos.col;int triedTime =  cellArray[row*colCnt+col].triedTime;Pos2D firstAvailPos = Pos2D::NotAvailablePos;Pos2D nextPosArray[] = { Pos2D(row,col+1),Pos2D(row,col-1)//right and left,Pos2D(row+1,col),Pos2D(row-1,col)//down and up};if(triedTime == 4)return Pos2D::NotAvailablePos;// try in right left down up orderbool bfind = false;while(triedTime < 4){ firstAvailPos = nextPosArray[triedTime]; Cell& nextCell = cellArray[firstAvailPos.row*colCnt+firstAvailPos.col]; if(nextCell.content == Maze::PASSAGE_CONTENT || nextCell.content == Maze::EXIT_CONTENT) { bfind = true; break; } triedTime++;}cellArray[row*colCnt+col].triedTime = triedTime; //update tried timeif(bfind)return firstAvailPos;elsereturn  Pos2D::NotAvailablePos;}
bool Maze::getoutOfMaze(pair
 
  ,list
  
   >& resultPair){Pos2D curPos = startPos;bool bfind = false;stack
   
     posStack;resultPair.second.push_front(curPos);do{   Cell& curNode = cellArray[curPos.row*colCnt+curPos.col];cellArray[curPos.row*colCnt+curPos.col].content = Maze::VISITED_CONTENT; //marked as visited //try at most four time(right left down up) to find a available neighbour nodePos2D nextAvailablePos = getFirstAvailablePos(curPos);if(nextAvailablePos != Pos2D::NotAvailablePos){   if(nextAvailablePos == exitPos) // successfully found path{resultPair.first.push_front(exitPos);resultPair.first.push_front(curPos);while(!posStack.empty()){resultPair.first.push_front(posStack.top());posStack.pop();}resultPair.second.push_back(exitPos);bfind = true; break;}posStack.push(curNode.pos); // push current pos to stackcurPos = nextAvailablePos;// set the next available pos as current posresultPair.second.push_back(curPos);}else{   //pop until we find a node has chance to trywhile(curNode.triedTime == 4 && !posStack.empty()){curPos = posStack.top();posStack.pop();curNode = cellArray[curPos.row*colCnt+curPos.col];resultPair.second.push_back(curPos);}if(posStack.empty()){   bfind = false; break;}}}while (!posStack.empty());    return bfind;}
   
  
 

Pair parameter of the above function , List > & ResultPair is a pair of linked lists that store two cell locations. The first linked list is used to save the searched path, and the second is used to save the entire process description of the elements that pass through the search process.

For example, the process of executing map 1 is:

input maze map file name:map1.txt---Finding Process---(8,3)   (9,3)   (9,4)   (9,5)   (8,5)   (7,5)   (6,5)   (5,5)   (5,6)   (5,7)(6,7)   (6,8)   (6,9)   (7,9)   (7,8)   (7,7)   (8,7)   (8,8)   (8,9)   (9,9)(9,8)   (9,7)   (9,8)   (9,9)   (8,9)   (8,8)   (8,7)   (7,7)   (7,8)   (7,9)(6,9)   (5,9)   (4,9)   (3,9)   (2,9)   (1,9)   (1,8)   (1,7)   (2,7)   (3,7)(3,6)   (3,5)   (3,4)   (3,3)   (2,3)   (2,4)   (2,5)   (1,5)   (1,4)   (1,3)(1,2)   (1,1)   (2,1)   (3,1)   (3,0)---Sum: 54 steps---Get out by :(8,3)           (9,3)           (9,4)           (9,5)           (8,5)(7,5)           (6,5)           (5,5)           (5,6)           (5,7)(6,7)           (6,8)           (6,9)           (5,9)           (4,9)(3,9)           (2,9)           (1,9)           (1,8)           (1,7)(2,7)           (3,7)           (3,6)           (3,5)           (3,4)(3,3)           (2,3)           (2,4)           (2,5)           (1,5)(1,4)           (1,3)           (1,2)           (1,1)           (2,1)(3,1)           (3,0)

For example, the process of executing map 2 is:

input maze map file name:map2.txt---Finding Process---(1,1)   (1,2)   (2,2)   (2,1)   (3,1)   (3,2)   (3,3)   (3,4)   (2,4)   (2,5)(2,6)   (1,6)   (1,5)   (1,4)   (1,5)   (1,6)   (2,6)   (2,5)   (2,4)   (3,4)(3,3)   (3,2)   (3,1)   (4,1)   (5,1)   (5,2)   (5,3)   (6,3)   (6,4)   (6,5)(7,5)   (8,5)   (8,6)   (8,7)   (8,8)---Sum: 34 steps---Get out by :(1,1)           (1,2)           (2,2)           (2,1)           (3,1)(4,1)           (5,1)           (5,2)           (5,3)           (6,3)(6,4)           (6,5)           (7,5)           (8,5)           (8,6)(8,7)           (8,8)


2.3 algorithm 2

Algorithms are easy to understand and conform to our conventional ideas. The algorithms are more concise but difficult to understand.

Provided by [2]The idea of algorithm 2 is as follows::

Set the portal to the current location. Each time starting from the current position, all the adjacent available units (Channel and not experienced) are put into the stack, and then the top element of the stack is taken out of the stack as the new current position, repeat the operation, the search is successful until the current position is the exit position. If the stack is empty before the exit is found, the search path fails.

Algorithm considerations: For this algorithm, the same unit may be added to the stack multiple times. However, when the same unit is output to the stack for the second time, the adjacent unit has been tried for the first time, so there will be no new unit in the stack. I call this unitDead Unit.

A simple example is used to describe the algorithm.

Map 7 (skipping many middle maps) is as follows:

11111111e0000111101111000001100m0011111111

The search process is as follows:

input maze map file name:map7.txt---Finding Process---(4,3)   (4,4)   (4,5)   (3,5)   (3,4)   (3,3)   (3,2)   (3,1)   (4,1)   (4,2)(4,2)   (2,3)   (1,3)   (1,4)   (1,5)   (1,2)   (1,1)---Sum: 16 steps---Get out by :(4,3)           (4,4)           (4,5)           (3,5)           (3,4)(3,3)           (3,2)           (3,1)           (4,1)           (4,2)(4,2)           (2,3)           (1,3)           (1,4)           (1,5)(1,2)           (1,1)

In this process, we can see that there are two useless attempts ()-() and () in the given path) -(), these are a feature of the algorithm, but the final program still finds the path. We should delete this useless path from the final result. How can we determine which paths are useless?

My opinionIf a current unit does not have a new adjacent unit in the stack, it indicates that the Unit is an dead unit. Then, the previous segment should be deleted. When will the Unit be deleted? The path where the node can be deleted to the next node. For example:

We found that () is a dead unit, so when the current unit is (), the top of the stack is (). We can trace back and find that () nodes can reach () in one step) therefore, you need to delete two nodes (1, 4) and (1, 5. According to this ideaAn algorithm that includes the deletion of invalid paths.:

// Push all Neighbour available posbool Maze: pushAllNeighbourCellStack (stack
 
  
& PosStack, Pos2D curPos) {int row = curPos. row, col = curPos. col; Pos2D nextPosArray [] = {Pos2D (row-1, col), Pos2D (row + 1, col) // up and down, Pos2D (row, col-1 ), pos2D (row, col + 1) // left and right}; bool bfind = false; for (int I = 0; I <4; I ++) {Pos2D nextPos = nextPosArray [I]; Cell & nextCell = cellArray [nextPos. row * colCnt + nextPos. col]; if (nextCell. content = Maze: PASSAGE_CONTENT | nextCell. content = Maze: EXIT_CONTENT) {bfind = true; posStack. push (nextPos) ;}} return bfind ;}// check if two pos can reach in one stepbool Maze: is2PosNeighbour (Pos2D & fisrtPos, Pos2D & secondPos) {bool bNeighbour = false; if (fisrtPos. row = secondPos. row) {if (fisrtPos. col-secondPos.col = 1 | fisrtPos. col-secondPos.col =-1) bNeighbour = true;} else if (fisrtPos. col = secondPos. col) {if (fisrtPos. row-secondPos.row = 1 | fisrtPos. row-secondPos.row =-1) bNeighbour = true;} return bNeighbour;} bool Maze: getoutOfMaze2 (pair
  
   
, List
   
    
> & ResultPair) {Pos2D curPos = startPos; stack
    
     
PosStack; bool bfind = false; while (curPos! = Maze: exitPos) {cellArray [curPos. row * colCnt + curPos. col]. content = Maze: VISITED_CONTENT; bfind = pushAllNeighbourCellStack (posStack, curPos); if (posStack. empty () {return false;} else {resultPair. second. push_back (curPos); if (bfind) {resultPair. first. push_back (curPos);} else // dead cell, modify the path {std: list
     
      
: Reverse_iterator rend = resultPair. first. rend (); std: list
      
        : Reverse_iterator rbegin = resultPair. first. rbegin (); list
       
         RemoveList; removeList. push_front (curPos); Pos2D nextPos = posStack. top (); while (rbegin! = Rend) {Pos2D & pos = * rbegin; if (is2PosNeighbour (nextPos, pos) {break;} else {removeList. push_front (pos); resultPair. first. remove (pos);} rbegin = resultPair. first. rbegin ();} std: cout <"remove path:" <
        
          (Std: cout, "\ t"); std: cout <
         
          
Test the preceding map 7 again and the results are as follows:

input maze map file name:map7.txtremove path:(4,2)remove path:(3,2)           (3,1)           (4,1)           (4,2)remove path:(1,4)           (1,5)---Finding Process---(4,3)   (4,4)   (4,5)   (3,5)   (3,4)   (3,3)   (3,2)   (3,1)   (4,1)   (4,2)(4,2)   (2,3)   (1,3)   (1,4)   (1,5)   (1,2)   (1,1)---Sum: 16 steps---Get out by :(4,3)           (4,4)           (4,5)           (3,5)           (3,4)(3,3)           (2,3)           (1,3)           (1,2)           (1,1)

After deleting the invalid sub-path this time, the simplest path is provided.


3. Unable to find the exit path

For example, MAP 4 is as follows:

In this case, the exit represented by a yellow block is surrounded by blocked channels and the exit path cannot be found. The test result of algorithm 1 is as follows:

input maze map file name:map4.txt---Finding Process---(1,1)   (1,2)   (2,2)   (2,1)   (3,1)   (3,2)   (3,3)   (3,4)   (2,4)   (2,5)(2,6)   (1,6)   (1,5)   (1,4)   (1,5)   (1,6)   (2,6)   (2,5)   (2,4)   (3,4)(3,3)   (3,2)   (3,1)   (4,1)   (5,1)   (5,2)   (5,3)   (6,3)   (6,4)   (6,5)(7,5)   (8,5)   (8,6)   (8,5)   (8,4)   (8,3)   (8,2)   (8,3)   (8,4)   (8,5)(7,5)   (6,5)   (5,5)   (5,6)   (5,7)   (5,8)   (6,8)   (6,7)   (6,8)   (5,8)(4,8)   (4,7)   (4,6)   (4,5)   (4,6)   (4,7)   (3,7)   (3,8)   (2,8)   (1,8)(2,8)   (3,8)   (3,7)   (4,7)   (4,8)   (5,8)   (5,7)   (5,6)   (5,5)   (6,5)(6,4)   (6,3)   (5,3)   (5,2)   (5,1)   (6,1)   (7,1)   (6,1)   (5,1)   (4,1)(3,1)   (2,1)   (2,2)   (1,2)   (1,1)---Sum: 84 steps---No Path to get out!

Algorithm 2 test results:

input maze map file name:map4.txtremove path:(1,5)           (1,4)remove path:(2,5)           (2,6)           (1,6)           (1,5)remove path:(3,2)           (3,3)           (3,4)           (2,4)           (1,4)remove path:(8,6)remove path:(7,5)           (8,5)           (8,4)           (8,3)           (8,2)remove path:(6,8)           (6,7)remove path:(4,6)           (4,5)remove path:(1,8)remove path:(5,8)           (4,8)           (4,7)           (3,7)           (3,8)(2,8)           (3,8)remove path:(6,7)remove path:(5,7)           (4,7)remove path:(5,6)           (4,6)remove path:(5,2)           (5,3)           (6,3)           (6,4)           (6,5)(5,5)           (4,5)remove path:(4,1)           (5,1)           (6,1)           (7,1)remove path:(3,2)---Finding Process---(1,1)   (1,2)   (2,2)   (2,1)   (3,1)   (3,2)   (3,3)   (3,4)   (2,4)   (2,5)(2,6)   (1,6)   (1,5)   (1,4)   (1,5)   (1,4)   (4,1)   (5,1)   (5,2)   (5,3)(6,3)   (6,4)   (6,5)   (7,5)   (8,5)   (8,6)   (8,4)   (8,3)   (8,2)   (5,5)(5,6)   (5,7)   (5,8)   (6,8)   (6,7)   (4,8)   (4,7)   (4,6)   (4,5)   (3,7)(3,8)   (2,8)   (1,8)   (3,8)   (6,7)   (4,7)   (4,6)   (4,5)   (6,1)   (7,1)(3,2)---Sum: 50 steps---No Path to get out!

Both algorithm 1 and algorithm 2 indicate that the path cannot be found after the attempt.


The program has been written here, and there are still a lot of thoughts on the maze issue, so we will wait for future reflection.


References:

[1] Adam Drozdek, the third edition of Data Structure and algorithm c ++, compiled by Tsinghua University Press

[2] Data Structure Yan Weimin Wu weiming Tsinghua University Press


Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.