迷宫算法——验证迷宫的可通性

【Qboy原创】

      记得在大学学习数据结构时就学过采用迭代方式可以判断一个迷宫是否有解无解甚至可以查找出所有的可能的出口。目前公司开发一个游戏需要玩家去搭建迷宫让其他玩家去闯迷宫的游戏,游戏其实很简单。但是有一个重点就是要验证玩家所搭建的迷宫是否可到达。好吧这就是我们接下去算法的需求。写下此文只是为了Mark过程。

  首先先创建必须的结构体

  (1)迷宫中所有的节点类型  

  typedef enum{
      EMPTY=0, //空白
      OBSTACLE, //障碍
      ENTER, //入口
      EXIT, //出口
    }MazeNodeType; //迷宫节点的类型

  根据不同的业务需求可能还涉及到其他的节点类型,这是最基础的类型。

  (2)迷宫节点:

  typedef struct
  {
    CCPoint location;//位置
    MazeNodeType nodeType;
  }MazeNode;

  (3)迷宫地图

  typedef struct
  {
    MazeNode** pMazeNode;//地图的节点
    int iMazeOrientation;//横向多少个
    int iMazeLongitudinal;//纵向

    MazeNode* pEnter;//入口

  }MazeMap;

  (4)定义走迷宫时的方向枚举

   typedef enum{
    UP = 0,//上
    LEFT,//左
    DOWN,//下
    RIGHT,//右
    MaxDirection
   } MazeDirection;//方向

  为了简单方便,定义了一个静态数组,描述每个方向中每个X、Y的变化值。

  static CCPoint pointDirection[]={ccp(0,1),ccp(-1,0),ccp(0,-1),ccp(1,0)};

  其次验证迷宫

bool checkMazeRoad(MazeMap& map, MazeNodeType selectType)
{
  CCAssert(map.pMazeNode!=NULL,"Map is NULL");
  CCAssert(map.iMazeOrientation>0,"Orientation must larger than 0");
  CCAssert(map.iMazeLongitudinal>0,"Longitudinal must larger than 0");
  std::stack<MazeNode*> sMazeNode;//未验证过的节点
  std::list<MazeNode*> lMazeNode;//已验证过的节点
  sMazeNode.push(map.pEnter);//入口进栈
  lMazeNode.push_back(map.pEnter);
  bool rtn = false;
  do
  {
    MazeNode* pnode = sMazeNode.top();
    sMazeNode.pop();

    for(int i = 0;i<MaxDirection&&!rtn;i++)//四个方向依次判断
    {
      int x = (int)(pnode->location.x+pointDirection[i].x);
      int y = (int)(pnode->location.y+pointDirection[i].y);

      if(x < 0 || x >= map.iMazeLongitudinal || y < 0 || y >= map.iMazeOrientation)
      {
        continue;//越界取下一个
      }

      MazeNode* newNode = &map.pMazeNode[x][y];
      std::list<MazeNode*>::iterator it = find(lMazeNode.begin(), lMazeNode.end(), newNode);
      if(it!=lMazeNode.end())//find 说明该点已经进行过判断或者还在栈中未处理不入栈
      {

        continue;

      }else{
        if(newNode->nodeType== selectType)//出口
        {
          rtn = true;
        }else if(newNode->nodeType==EMPTY){//空白点进栈便于下次检查
          lMazeNode.push_back(newNode);
          sMazeNode.push(newNode);
        }
      }
    }

  } while (sMazeNode.size()>0&&!rtn);//无出口或者已经找到出口
  return rtn;
}

由于该功能只是为了满足是否有出口无需判断出口路线,如果需要有出口路线,则在迷宫节点添加一个指向前面节点的指针,然后用反向找到迷宫路径。

该功能比较简单,所以直接上代码了,见谅。

posted @ 2014-11-22 16:18  qboy2010  阅读(475)  评论(0编辑  收藏  举报