溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

求迷宮通路問題

發(fā)布時間:2020-05-04 18:49:57 來源:網(wǎng)絡(luò) 閱讀:642 作者:腳印C 欄目:編程語言

    本次我們探討一下迷宮小游戲。

讓我們來探討一下怎樣可以得到一條通路,采用棧來實現(xiàn)。

    當(dāng)是通路的時候,節(jié)點壓棧。當(dāng)走到盡頭不通時,出棧,尋找交叉口,尋找通路。

求迷宮通路問題

像這樣在第一行存放迷宮的規(guī)格(在這里為傳參少,定義正方形迷宮),設(shè)計迷宮,將迷宮以.txt格式存放在目錄下(可以是任何地方,下文以默認(rèn)路徑為例)。

    假設(shè)入口為(2,0),出口為迷宮最后一行任意位置。


    MAZE.h

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

class Pos  //迷宮每一點的坐標(biāo)
{
public:
 Pos(int row,int col)
  :_row(row)
  , _col(col)
 {}

 int _row;
 int _col;
};


void PrintPos(Pos& pos)// 打印節(jié)點坐標(biāo)
{
 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)  //判斷是否為終點:設(shè)迷宮終點為能到達(dá)迷宮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) //尋找通路
{
 //若某一位置節(jié)點為0,進行壓棧,且將數(shù)據(jù)改為2,尋找此節(jié)點上下左右位置為0的節(jié)點,再進行壓棧,
 //若某一位置上下左右沒有為0的節(jié)點,就出棧尋找上一個節(jié)點上下左右為0的節(jié)點進行壓棧 
 assert(a);
 Pos top = paths.top();
 a[top._row*N + top._col] = 2;
 while (!IsOverScope(paths.top(), N))//每次都要判斷坐標(biāo)是否越界、還要考慮出口旁邊也是出口的情況就會多走幾次
 {

  //判斷是否到達(dá)出口
  if (IsEndPoint(top, N))
  {
   return true;
  }

  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 (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()
{
 //假設(shè)迷宮為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;
}


讓我們來看看運行結(jié)果。


求迷宮通路問題


再試試將最后一行的‘0’改為1,讓它變成無通路的迷宮


求迷宮通路問題


我們可以在思考一下:

    當(dāng)有好幾條通路的時候,我們可以得到最短路嗎?

求迷宮通路問題


我們可以得到以下思路:

    記錄最小路的步數(shù) ,到達(dá)出口時將出口變?yōu)? ,尋找下一條出口,然后更新最短路.

若要尋找這條最短路,那就可以在尋找一次,當(dāng)通路的步數(shù)與最短路步數(shù)一致時輸出通路。


    但是上述方法存在很大的問題:雖然可以得到一個結(jié)果,但是不能夠保證就是最短的。

因為,當(dāng)按照上述編程尋找通路的邏輯 “上右下左” 順序?qū)ふ彝窌r,就可能會把另一條更短的通路堵住,從而影響最短路的結(jié)果。


求迷宮通路問題


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

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI