Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 681723
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 14, 20262026-05-14T01:30:54+00:00 2026-05-14T01:30:54+00:00

I traverse a 16×16 maze using my own A* implementation. All is well. However,

  • 0

I traverse a 16×16 maze using my own A* implementation.

All is well. However, after the traversal, I would like to find out what wall would give me the best alternative path. Apart from removing every block and re-running A* on the maze, what’s a more clever and elegant solution?

I was thinking give every wall node (ignored by A*), a tentative F-value, and change the node structure to also have a n-sized list of node *tentative_parent where n is the number of walls in the maze. Could this be viable?

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-14T01:30:54+00:00Added an answer on May 14, 2026 at 1:30 am

    When you add a node to the list of nodes to consider, also add a flag whether the path through that node has already gone through a wall.

    possibleNode.heuristic = currentNode.distance + heuristicEstimate(possibleNode)
    possibleNode.goneThroughWall = currentNode.goneThroughWall || possibleNode.isAWall
    allPossiblePaths.insert(possibleNode) // Priority queue sorted on Node.heuristic
    

    Then when considering possible paths from a node, if it hasn’t gone through a wall, consider adjacent walls to be fair paths.

    foreach neighborNode in neighbors(someNode)
        if !(someNode.goneThroughWall && neighborNode.isAWall)
            addToPossiblePaths(neighborNode)
    

    You already have to maintain distance from the start node to the current node being processed, and it uses what you already have in place.

    Full proof of concept:

    We see that operator== is defined to also consider whether or not the path has hit a wall yet. This allows us to consider the a node twice if needed, when we look in the closed set to see if we have already encountered this node. This is the case in the center hallway in the example maze in the source below.

    The portions of code marked with #ifdef I_AM_ALLOWED_TO_GO_THROUGH_A_WALL show the portions needed to augment a normal A* algorithm to be able to go through a single wall.

    #include <cassert>
    #include <algorithm>
    #include <cstdlib>
    #include <iostream>
    #include <set>
    #include <vector>
    
    #define I_AM_ALLOWED_TO_GO_THROUGH_A_WALL
    
    const int width  = 5;
    const int height = 5;
    
    // Define maze
    const int maze[height][width] =
      { { 0, 1, 1, 0, 0 },
        { 0, 1, 0, 1, 0 },
        { 0, 1, 0, 1, 0 },
        { 0, 1, 0, 1, 0 },
        { 0, 0, 0, 0, 0 } };
    
    // Square represents the actual structure of the maze
    // Here, we only care about where it is, and whether it is a wall
    struct Square {
      Square(int _x, int _y)
        : x(_x), y(_y) {}
    
      bool operator==(const Square& rhs) const {
        return x == rhs.x && y == rhs.y;
      }
    
      bool isAWall() const {
        return maze[y][x];
      }
    
      int distance(const Square& goal) const {
        return std::abs(x - goal.x) + std::abs(y - goal.y);
      }
    
      int x;
      int y;
    };
    
    // Define start and end of maze
    const Square goalSquare(3, 0);
    const Square startSquare(0, 0);
    
    // A PathNode describes the A* algorithm's path through the maze
    // It keeps track of its associated Square
    //                   its previous PathNode in the path
    //                   the length of the path up to the current PathNode
    //                   whether the path so far has goneThroughWall
    struct PathNode {
      explicit PathNode(const Square& s, int length = 0, const PathNode* _prev = NULL)
        : square(s),
          prev(_prev),
          pathLength(length) {
        heuristic = pathLength + square.distance(goalSquare);
    
    #ifdef I_AM_ALLOWED_TO_GO_THROUGH_A_WALL
        if(prev)
          goneThroughWall = prev->goneThroughWall || square.isAWall();
        else
          goneThroughWall = false;
    
        // Sanity check, these should be the same
        assert(goneThroughWall == hasGoneThroughAWall());
    #endif
      }
    
      bool operator<(const PathNode& rhs) const {
        return heuristic < rhs.heuristic;
      }
    
      // This is very important. When examining the closed set to see
      // if we've already evaulated this node, we want to differentiate
      // from whether we got to that node using a path through a wall.
      //
      // This is especially important in the given example maze.
      // Without this differentiation, paths going up column 3 will hit
      // old, closed paths going through the walls in column 2, and not
      // find the best path.
      bool operator==(const PathNode& rhs) const {
        return square == rhs.square
    #ifdef I_AM_ALLOWED_TO_GO_THROUGH_A_WALL
          && goneThroughWall == rhs.goneThroughWall
    #endif
          ;
      }
    
      bool weakEquals(const PathNode& rhs) const {
        return square == rhs.square;
      }
    
      bool weakEquals(const Square& rhs) const {
        return square == rhs;
      }
    
      // Sanity checker
      bool hasGoneThroughAWall() const {
        if(square.isAWall()) return true;
    
        const PathNode* p = prev;
        while(p) {
          if(p->square.isAWall())
            return true;
          p = p->prev;
        }
    
        return false;
      }
    
      Square square;
      const PathNode* prev;
      int heuristic, pathLength;
    #ifdef I_AM_ALLOWED_TO_GO_THROUGH_A_WALL
      bool goneThroughWall;
    #endif
    };
    
    std::ostream& operator<<(std::ostream& ostr, const PathNode& p) {
      ostr << "(" << p.square.x << ", " << p.square.y << ")";
      if(p.square.isAWall())
        ostr << " <- Wall!";
      return ostr;
    }
    
    std::vector<Square> getNeighbors(const Square& s) {
      std::vector<Square> neighbors;
    
      if(s.x > 0)
        neighbors.push_back(Square(s.x - 1, s.y));
      if(s.x < width - 1)
        neighbors.push_back(Square(s.x + 1, s.y));
      if(s.y > 0)
        neighbors.push_back(Square(s.x, s.y - 1));
      if(s.y < height - 1)
        neighbors.push_back(Square(s.x, s.y + 1));
    
      return neighbors;
    }
    
    void printList(const PathNode* p, int i = 0) {
      if(p) {
        printList(p->prev, i + 1);
        std::cout << *p << std::endl;
      } else {
        std::cout << "Length: " << i << std::endl;
      }
    }
    
    typedef std::multiset<PathNode> Set;
    
    int main(int argc, char** argv) {
      // Print out maze
      for(int j = 0; j < height; ++j) {
        for(int i = 0; i < width; ++i) {
          std::cout << " " << maze[j][i];
        }
        std::cout << std::endl;
      }
      std::cout << std::endl;
    
      Set closedSet;
      Set openSet;
      openSet.insert(PathNode(startSquare)); // Start node (defined at line ~42)
    
      int processedCount = 0;
      while(!openSet.empty()) {
        Set::iterator currentNode = openSet.begin();
        ++processedCount;
    
        // We've found the goal, so print solution.
        if(currentNode->weakEquals(goalSquare)) {
          std::cout << "Processed nodes: " << processedCount << std::endl;
          printList(&*currentNode);
          return 0;
        }
    
        {
          // Move from open set to closed set
          Set::iterator del = currentNode;
          currentNode = closedSet.insert(*currentNode);
          openSet.erase(del);
        }
    
        std::vector<Square> neighbors = getNeighbors(currentNode->square);
        for(unsigned int i = 0; i < neighbors.size(); ++i) {
          PathNode currentNeighbor(neighbors[i], currentNode->pathLength + 1, &*currentNode);
    
          // Skip if it is 2nd wall
          if(
    #ifdef I_AM_ALLOWED_TO_GO_THROUGH_A_WALL
            currentNode->goneThroughWall &&
    #endif
            currentNeighbor.square.isAWall()
          )
            continue;
    
          // Skip if it is already in the closed set
          // Note: Using std::find here instead of std::multiset::find because
          // std::multiset::find uses the definition !(a < b) && !(b < a) for
          // searching. I want it to use my overloaded a == b.
          if(find(closedSet.begin(), closedSet.end(), currentNeighbor) != closedSet.end())
            continue;
    
          // Skip if we were just there
          const PathNode* p = currentNode->prev;
          if(p && p->weakEquals(currentNeighbor))
            continue;
    
          // See if there is a better alternative in the open set
          // Note: Using std::find here instead of std::multiset::find. See above.
          Set::iterator contender = find(openSet.begin(), openSet.end(), currentNeighbor);
          if(contender == openSet.end())
            openSet.insert(currentNeighbor);
          else if(currentNeighbor.pathLength < contender->pathLength) {
            // We've found a better alternative, so replace
            openSet.erase(contender);
            openSet.insert(currentNeighbor);
          }
        }
      }
    
      std::cout << "Failure." << std::endl;
      return 1;
    }
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I'm using the File::Find module to traverse a directory tree. Once I find a
I'm trying to traverse through all the subdirectories of the current directory in Perl,
How do you traverse a folder structure using C# without falling into the trap
I'm currently using SMO and C# to traverse databases to create a tree of
How do I traverse a list in reverse order in Python? So I can
How to create a C++ Boost undirected graph and traverse it in depth first
I've written the following routine to manually traverse through a directory and calculate its
Can someone show me how to implement a recursive lambda expression to traverse a
I've got a 1-based array of four items which I need to traverse. For
I have a RootViewController and a SubViewController. I traverse the views in either direction.

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.