用棧實現迷宮遊戲尋路

    在咱們學習數據結構的時候都曾經見過迷宮遊戲,迷宮遊戲的實現其實並不難,可是,咱們在實現每個算法的時候都應該想想這個問題的每個解。最近,博主已經開始重溫數據結構啦,記得咱們之前學習這裏的時候,老師會用隊列來實現迷宮最優解的尋找,氮素呢,博主就是這麼可愛,博主就是想試試用棧來找一下。ios

    在實現以前讓咱們先來複習一下棧的特色:first in last out
c++

    對於棧這種數據結構咱們只能在棧頂對其操做,根據實際狀況可將其實現成鏈式或者順序結構。可是通常狀況下咱們都會實現成順序結構,由於棧的特色致使了順序結構管理方便,而且CPU緩存利用率更高。下面咱們來簡單的講解一下迷宮小遊戲算法

     爲了不用戶操做的不便性,咱們選擇將迷宮提早寫好放在一個叫作"Maze.h"的文件中緩存

 

wKioL1cKG7ThltAWAAAbMDW4B8g037.png

*第一行的兩個數字是迷宮的行和列數據結構

    咱們解決迷宮尋路問題的基本思想是回溯。回溯是什麼意思呢? 就是說,找不到就回退的思想。今天咱們的程序要解決的問題是尋找最優解,因此,迷宮的每一條路咱們都要去走一遍,這樣,咱們才能找到最短的那條路。ide

咱們先來看一下程序是怎麼寫的(若是噴,請輕點j_0030.gif學習

#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

    上面的代碼呢,其實寫的很是的很差,尤爲是在代碼複用的方面,不過,博主今天只是來舉個栗子,從此會更加註意,大家也要注意哦,上面是個反面教材j_0084.gif(請理解一個看見本身代碼想吐的我)blog


 解法詳解:用一個全局的棧結構來存儲最優路徑 min隊列

           用一個局部的站結構來存儲當前一次得出的路徑 s1

           每一步都須要判斷上下左右四個方向是否可走

           ***注意:每次判斷時將next的值先賦成當前的位置再進行加減不然產生反作用

           兩層循環:裏面一層即當前一次尋路完成

           外面一層即再也無路可循時咱們得到了最優解

**嗯,再看一眼仍然以爲這個代碼看得我辣眼睛(捂臉)。

請圍觀羣衆不吝賜教哦~

相關文章
相關標籤/搜索