求迷宫通路问题

本次我们探讨一下迷宫小游戏。

让我们来探讨一下怎样可以得到一条通路,采用栈来实现。

当是通路的时候,节点压栈。当走到尽头不通时,出栈,寻找交叉口,寻找通路。

像这样在第一行存放迷宫的规格(在这里为传参少,定义正方形迷宫),设计迷宫,将迷宫以.txt格式存放在目录下(可以是任何地方,下文以默认路径为例)。

假设入口为(2,0),出口为迷宫最后一行任意位置。

MAZE.h

#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;
#include<assert.h>
#include<stack>

class Pos  //迷宫每一点的坐标
{
public:
 Pos(int row,int col)
  :_row(row)
  , _col(col)
 {}

 int _row;
 int _col;
};

void PrintPos(Pos& pos)// 打印节点坐标
{
 cout << "(" << pos._row << ", " << pos._col << ") ";
}

int* GetMaze(int& N)//从文件中打开迷宫
{
 FILE *font = fopen("maze.txt", "r");
 assert(font != NULL);//打不开迷宫文件无意义

 char ch;
 while ((ch = fgetc(font)) != ‘\n‘)
 {
  N = N * 10 + ch - ‘0‘;
 }

 int *a = new int[N*N];
 for (int i = 0; i < N*N, (ch = fgetc(font)) != EOF;)
 {
  if (ch == ‘1‘ || ch == ‘0‘)
  {
   a[i] = ch - ‘0‘;
   i++;
  }
 }
 return a;
}

void PrintMaze(int *a, const int N)//打印迷宫
{
 cout << "\n迷宫地图  (‘0‘为路, ‘1‘为墙)" << endl;

 for (int i = 0; i < N; i++)
 {
  for (int j = 0; j < N; j++)
  {
   cout << a[i * 10 + j] << " ";
  }
  cout << endl;
 }
}

bool IsOverScope(Pos pos, const int N)//判断是否越界
{
 if (pos._col < 0 || pos._col >= N || pos._row < 0 || pos._row >= N)
 {
  return true;
 }
 return false;
}

bool IsEndPoint(Pos pos, const int N)  //判断是否为终点:设迷宫终点为能到达迷宫N-1行
{
 if (pos._col >= 0 && pos._col < N && pos._row == N - 1)
 {
  return true;
 }
 return false;
}

bool SearchMazePath(int* a, const int N, Pos enrty, stack<Pos>& paths) //寻找通路
{
 //若某一位置节点为0,进行压栈,且将数据改为2,寻找此节点上下左右位置为0的节点,再进行压栈,
 //若某一位置上下左右没有为0的节点,就出栈寻找上一个节点上下左右为0的节点进行压栈 
 assert(a);
 Pos top = paths.top();
 a[top._row*N + top._col] = 2;
 while (!IsOverScope(paths.top(), N))//每次都要判断坐标是否越界
 {
  
  if (0 == a[(top._row - 1)*N + top._col])//上
  {
   a[(top._row - 1)*N + top._col] = 2;
   Pos tmp(top._row - 1, top._col);
   paths.push(tmp);
   top = paths.top();
   continue;
  }
  if (0 == a[top._row * N + top._col + 1])//右
  {
   a[top._row * N + top._col + 1] = 2;
   Pos tmp(top._row, top._col + 1);
   paths.push(tmp);
   top = paths.top();
   continue;
  }

  if (0 == a[(top._row + 1)*N + top._col])//下
  {
   a[(top._row + 1)*N + top._col] = 2;
   Pos tmp(top._row + 1, top._col);
   paths.push(tmp);
   top = paths.top();
   continue;
  }
  if (0 == a[top._row * N + top._col - 1])//左
  {
   a[top._row * N + top._col - 1] = 2;
   Pos tmp(top._row, top._col - 1);
   paths.push(tmp);
   top = paths.top();
   continue;
  }
  //if (0 == a[top._row * N + top._col + 1] && top._col + 1 < N)//右
  //{
  // a[top._row * N + top._col + 1] = 2;
  // Pos tmp(top._row, top._col + 1);
  // paths.push(tmp);
  // top = paths.top();
  // continue;
  //}

  //判断是否到达出口
  if (IsEndPoint(top, N))
  {
   return true;
  }
  
  //回退
  if (a[top._row*N + top._col] == 2 && !paths.empty())
  {
   paths.pop();
   if (!paths.empty())
   {
    top = paths.top();   
    continue;
   }
   else
   {
    return false;
   }
  }
 }

 //if (IsOverScope(top, N) || paths.empty())//从上左右出来 
 return false;
 
}
 
void PrintPath(stack<Pos> paths)  //打印通路
{
 //最少Paths中有一个元素enrty在最底层
 assert(!paths.empty());
 cout << "通路: " << endl;;
 while (!paths.empty())
 {
  PrintPos(paths.top());
  paths.pop();
 }

 cout << endl;
}

test.cpp

#include"MAZE.h"

void test()
{
 //假设迷宫为N*N型正方形

 int N = 0;
 int *a = GetMaze(N);
 PrintMaze(a, N);

 Pos enrty(2,0);

 stack<Pos> paths;
 paths.push(enrty);

 if (SearchMazePath((int*)a, N, enrty, paths))
 {
  PrintMaze(a, N);
  PrintPath(paths);
 }
 else
 {
  PrintMaze(a, N);
  cout << "There is not a path in this maze!" << endl;
 }

}

int main()
{
 test();

 system("pause");
 return 0;
}

让我们来看看运行结果。

再试试将最后一行的‘0’改为1,让它变成无通路的迷宫

我们可以在思考一下:

当有好几条通路的时候,我们可以得到最短路吗?

我们可以得到以下思路:

记录最小路的步数 ,到达出口时将出口变为1 ,寻找下一条出口,然后更新最短路.

若要寻找这条最短路,那就可以在寻找一次,当通路的步数与最短路步数一致时输出通路。

但是上述方法存在很大的问题:虽然可以得到一个结果,但是不能够保证就是最短的。

因为,当按照上述编程寻找通路的逻辑 “上右下左” 顺序寻找通路时,就可能会把另一条更短的通路堵住,从而影响最短路的结果。

那到底怎么做呢? 期待下一篇博客。

时间: 2024-12-19 10:21:38

求迷宫通路问题的相关文章

求迷宫多条最短路径

#include <iostream> #include <string> #include <cstdio> #include <cstring> #include <cstdlib> #include <queue> #include <stack> using namespace std; const int SIZE = 102; //边界数组,四个方向,按照下.右.上.左的顺序 int coordinate[4]

8.24 求最短通路值

[题目]: 用一个整型矩阵matrix表示一个网络,1代表有路,0代表无路,每一个位置只要不越界,都有上下左右4个方向,求从最左上角到最右下角的最短通路值 例如,matrix为: 1 0 1 1 1 1 0 1 0 1 1 1 1 0 1 0 0 0 0 1 通路只有一条,由12个1构成,所以返回12 题目来源:左程云老师<程序员代码面试指南> 原文地址:https://www.cnblogs.com/latup/p/10205035.html

回溯法求迷宫问题

回溯法(探索与回溯法)是一种选优搜索法,又称为试探法,按选优条件向前搜索,以达到目标.但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”.本文使用回溯法求解迷宫问题迷宫问题,有一个m行n列的矩阵代表迷宫,1代表此路不通,0代表此路通.指定入口和出口,判断是否能从入口进,从出口走出.此程序只判断从路口到出口是否能走通,找到的路不一定是最短路(最短路的程序在下一篇中使用BFS算法给出),注意:从入口到

DFS求迷宫问题

/* 迷宫问题(四方向) input: 1 6 8 0 1 1 1 0 1 1 1 1 0 1 0 1 0 1 0 0 1 0 0 1 1 1 1 0 1 1 1 0 0 1 1 1 0 0 1 1 0 0 0 0 1 1 0 0 1 1 0 output: YES (1,1) (2,2) (3,1) (4,1) (5,2) (5,3) (6,4) (6,5) (5,6) (4,5) (4,6) (5,7) (5,8) (6,8) (递归) (1,1) (2,2) (3,3) (3,4) (4,

迷宫问题算法设计与实现

迷宫求解 求迷宫中从入口到出口的所有路径是一个经典的程序设计问题.由于计算机解迷宫时,通常用的是"穷举求解"的方法,即从入口出发,顺某一方向向前探索,若能走通,则继续往前走:否则沿原路退回,换一个方向再继续探索,直至所有可能的通路都探索到为止.为了保证在任何位置上都能沿原路退回,显然需要用一个后进先出的结构来保存从入口到当前位置的路径.因此,在求迷宫通路的算法中应用"栈"也就是自然而然的事了.  假设迷宫如下图所示: 1 1 1 1 1 1 1 1 1 0 1 1

Frogger POJ - 2253(求两个石头之间”所有通路中最长边中“的最小边)

题意 ? 题目主要说的是,有两只青蛙,在两个石头上,他们之间也有一些石头,一只青蛙要想到达另一只青蛙所在地方,必须跳在石头上.题目中给出了两只青蛙的初始位置,以及剩余石头的位置,问一只青蛙到达另一只青蛙所在地的所有路径中的"the frog distance"中的最小值. ? 解释一下"the frog distance": 题目中给出了一段解释"The frog distance (humans also call it minimax distance

初级版迷宫问题(栈的应用)

  /*  (一)初级迷宫问题:   0:代表通   1:代表不通   求迷宫的通路  (二)步骤:   1.创建迷宫      * 从文件中读取迷宫      * 开辟二维数组存放迷宫   2.寻找通路      * 检查某位置是否为通      * 出口位置判断      * 走过的路用2标记      * 利用栈回溯  (三)问题   1.解决回溯中重复探测:递归   2.最优解:迷宫的最短通路 */ #include <iostream> #include <stdlib.h&g

栈与回溯:迷宫问题

迷宫问题是栈的典型应用,栈通常也与回溯算法连用. 回溯算法的基本描述是: (1)  选择一个起始点: (2)  如果已达目的地, 则跳转到 (4): 如果没有到达目的地, 则跳转到 (3) ; (3)  求出当前的可选项: a.  若有多个可选项,则通过某种策略选择一个选项,行进到下一个位置,然后跳转到 (2); b.  若行进到某一个位置发现没有选项时,就回退到上一个位置,然后回退到 (2) ; (4) 退出算法. 在回溯算法的实现中,通常要使用栈来保存行进中的位置及选项.本文给出自己写的迷宫

用栈实现的迷宫问题

迷宫问题中为了保证任何位置上都能沿原路退回,显然需要用一个先进后出的结果来保存从入口到当前位置的路径.因此,在迷宫通路的算法中应用“栈”也是自然而然的事情 头文件: #define STACK_INIT_SIZE 100 #define STACKINCREMENT 10 #define TRUE 1 #define FALSE 0 #define OK 1 #define ERROR 0 #define INFEASIBLE -1 #define MYOVERFLOW -2 typedef i