您好,登錄后才能下訂單哦!
本次我們探討一下迷宮小游戲。
讓我們來探討一下怎樣可以得到一條通路,采用棧來實現。
當是通路的時候,節點壓棧。當走到盡頭不通時,出棧,尋找交叉口,尋找通路。
像這樣在第一行存放迷宮的規格(在這里為傳參少,定義正方形迷宮),設計迷宮,將迷宮以.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 (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() { //假設迷宮為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 ,尋找下一條出口,然后更新最短路.
若要尋找這條最短路,那就可以在尋找一次,當通路的步數與最短路步數一致時輸出通路。
但是上述方法存在很大的問題:雖然可以得到一個結果,但是不能夠保證就是最短的。
因為,當按照上述編程尋找通路的邏輯 “上右下左” 順序尋找通路時,就可能會把另一條更短的通路堵住,從而影響最短路的結果。
那到底怎么做呢? 期待下一篇博客。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。