在咱们学习数据结构的时候都曾经见过迷宫游戏,迷宫游戏的实现其实并不难,可是,咱们在实现每个算法的时候都应该想想这个问题的每个解。最近,博主已经开始重温数据结构啦,记得咱们之前学习这里的时候,老师会用队列来实现迷宫最优解的寻找,氮素呢,博主就是这么可爱,博主就是想试试用栈来找一下。ios
在实现以前让咱们先来复习一下栈的特色:first in last out
c++
对于栈这种数据结构咱们只能在栈顶对其操做,根据实际状况可将其实现成链式或者顺序结构。可是通常状况下咱们都会实现成顺序结构,由于栈的特色致使了顺序结构管理方便,而且CPU缓存利用率更高。下面咱们来简单的讲解一下迷宫小游戏算法
为了不用户操做的不便性,咱们选择将迷宫提早写好放在一个叫作"Maze.h"的文件中缓存
*第一行的两个数字是迷宫的行和列数据结构
咱们解决迷宫寻路问题的基本思想是回溯。回溯是什么意思呢? 就是说,找不到就回退的思想。今天咱们的程序要解决的问题是寻找最优解,因此,迷宫的每一条路咱们都要去走一遍,这样,咱们才能找到最短的那条路。ide
#define _CRT_SECURE_NO_WARNINGS 1 #pragma once #include<cassert> #include<iostream> #include<fstream> #include<stack> using namespace std; struct Pos { size_t _x; size_t _y; Pos(size_t x, size_t y) :_x(x), _y(y) {} }; stack<Pos> min; bool IsValid(int *a, Pos cur, size_t R, size_t C) { if ((a[cur._x*C + cur._y] == 0) && (cur._x < R) && (cur._y < C)) return true; else return false; } void PrintMap(int *Map, size_t m, size_t n) { for (size_t i = 0; i < m; i++) { for (size_t j = 0; j < n; j++) { std::cout << Map[i*n + j] << " "; } std::cout << std::endl; } } void GetMaze(int *a,size_t Row,size_t Col,std::ifstream& fout) { size_t ch = 0; for (size_t i = 0; i < Row; i++) { for (size_t j = 0; j < Col;) { ch = fout.get()-'0'; if (ch == 0 || ch == 1) { a[i*Col + j] = ch; j++; } else continue; } } PrintMap(a, Row, Col); } bool Check(int *a,Pos entry,int R,int C) { Pos Up = entry; Pos Down = entry; Pos Left = entry; Pos Right = entry; Down._x++; Right._y++; Up._x--; Left._y--; if (IsValid(a, Down, R, C) || IsValid(a, Up, R, C) || IsValid(a, Left, R, C) || IsValid(a, Right, R, C)) return true; else return false; } bool GamePlay(int *a, Pos entry, size_t R, size_t C) { assert(a); stack<Pos> s1; Pos man = entry; Pos next = man; Pos cur = entry; while ( 1 ) { if (!Check(a, man, R, C)) { cout << "最佳路径长度:"; cout << min.size() << endl; return true; } s1.push(man); while (!s1.empty()) { a[man._x*C + man._y] = 2; if (man._x == (R - 1) || man._y == (C - 1)) { cout << "Find&end" << endl; if ((s1.size() < min.size()) || min.size() == 0) min = s1; while (!s1.empty()) { cur = s1.top(); s1.pop(); if (Check(a, cur, R, C)) { man = cur; break; } } if (s1.empty()) { cout << "最佳路径长度:"; cout << min.size() << endl; return true; } } //********************************************下 next = man; next._x++; if (IsValid(a, next, R, C)) { s1.push(man); man = next; continue; } //********************************************右 next = man; next._y++; if (IsValid(a, next, R, C)) { s1.push(man); man = next; continue; } //********************************************左 next = man; next._y--; if (IsValid(a, next, R, C)) { s1.push(man); man = next; continue; } //********************************************上 next._x--; if (IsValid(a, next, R, C)) { s1.push(man); man = next; continue; } else { man = s1.top(); s1.pop(); } } man = entry; } } void GameTest() { //**********************从文件读入迷宫大小********************** ifstream fout("Maze.txt"); stack<int> s1; int Row = 0; int Col = 0; char ch = fout.get(); while (ch != ' ') { int tmp = ch - '0'; s1.push(tmp); ch = fout.get(); } int c = 0; while (!s1.empty()) { Row += s1.top()*(int)pow(10, c); s1.pop(); c++; } ch = fout.get(); while (ch != ' '&&ch != '\n') { int tmp = ch - '0'; s1.push(tmp); ch = fout.get(); } c = 0; while (!s1.empty()) { Col += (int)s1.top()*(int)pow(10, c); s1.pop(); c++; } int *a = new int[Row*Col]; //******************************************************** Pos entry(0, 1); cout << endl << "*********** Map **********" << endl; GetMaze(a, Row, Col, fout); GamePlay(a, entry, Row, Col); cout << endl << "*********** Map **********" << endl; PrintMap(a, Row, Col); fout.close(); }
**记得在打开文件的时候作异常处理哦。博主在这里就不改了,小伙伴们本身看看spa
上面的代码呢,其实写的很是的很差,尤为是在代码复用的方面,不过,博主今天只是来举个栗子,从此会更加注意,大家也要注意哦,上面是个反面教材(请理解一个看见本身代码想吐的我)blog
解法详解:用一个全局的栈结构来存储最优路径 min队列
用一个局部的站结构来存储当前一次得出的路径 s1
每一步都须要判断上下左右四个方向是否可走
***注意:每次判断时将next的值先赋成当前的位置再进行加减不然产生反作用
两层循环:里面一层即当前一次寻路完成
外面一层即再也无路可循时咱们得到了最优解
**嗯,再看一眼仍然以为这个代码看得我辣眼睛(捂脸)。
请围观群众不吝赐教哦~