以棧解決迷宮問題

    怎麼找到一個迷宮的出口呢。首先要知道迷宮長啥樣,以後知道出入口,再以後就是找通路的過程了。
ios

    顯然主要的部分是如何找通路。咱們就舉一個例子:
數組

wKiom1c9duXx9BJ0AAAEpBmw1qY091.png

    在這個迷宮中0就是牆,1就是路。那麼咱們能夠用一個二維數組來表示這個迷宮。以後咱們須要一種結構來實現咱們表示位置的移動。ide

struct Pos
{
	size_t line;
	size_t row;
};

    這個結構體經過記錄行和列來表示如今處在迷宮的哪一個位置。
函數

    如今就能夠開始進行找通路的過程了。咱們很容易想到經過試探當前位置的周圍四個或三個位置來找到下一個應該去的位置,直到走到出口就算任務完成了。可是咱們在試探的過程當中,走到了下個位置,必定要把以前的位置作一個標記,不然咱們的程序會一直在兩個位置之間走來走去。咱們這裏經過把以前的位置置爲2來防止它走來走去。
spa

                if (pos.row>0 && maze[pos.line * 10 + pos.row - 1] == 1)//左
		{
			p.push(pos.line * 10 + pos.row);
			pos.row--;
			maze[(pos.line * 10 + pos.row)] = 2;
		}
		else if (pos.row < 9 && maze[pos.line * 10 + pos.row + 1] == 1)//右
		{
			p.push(pos.line * 10 + pos.row);
			pos.row++;
			maze[(pos.line * 10 + pos.row)] = 2;
		}
		else if (pos.line > 0 && maze[(pos.line - 1) * 10 + pos.row] == 1)//上
		{
			p.push(pos.line * 10 + pos.row);
			pos.line--;
			maze[(pos.line * 10 + pos.row)] = 2;
		}
		else if (pos.line < 9 && maze[(pos.line + 1) * 10 + pos.row] == 1)//下
		{
			p.push(pos.line * 10 + pos.row);
			pos.line++;
			maze[(pos.line * 10 + pos.row)] = 2;
		}

    這段代碼就是對上下左右四個方向進行試探的過程,其中咱們用一個棧記錄下了咱們走過的位置,由於迷宮裏面有岔路,因此咱們走錯時須要進行回溯。而選用棧是由於棧的後進先出的特性。說到走進岔路進行回溯,當咱們發現上面四種試探完成卻沒有通路時,就是咱們已經走到了死衚衕的最深處,須要進行回溯了,那末回溯的過程就是進行拿取棧頂元素,以後出棧的過程。指針

                        maze[(pos.line * 10 + pos.row)] = 3;
			pos.line = p.top() / 10;
			pos.row = p.top() - pos.line*10;
			p.pop();

    上面的代碼就是進行回溯的過程,再加一個是否到達終點的判斷就完成了主要部分。
blog

                if (pos.line * 10 + pos.row == 91)
		{
			PrintMaze(maze);
			return 1;
		}


    上面就是找路徑的過程,也就是咱們代碼的主要邏輯部分。剩下的就是一些注意事項。
內存

    讀迷宮圖我是經過文件指針,fopen,fgets,fclose來實現的。以後在建立了一個二維數組以後咱們給函數傳參的時候須要把它轉換成一個一級指針來傳遞。咱們操做就把它看成一個一維數組來處理。由於在內存中一維數組和二維數組是同樣的,只不過表示方式不同而已,咱們這個迷宮經過二維數組表示比較直觀,可是用一維數組同樣能夠處理。
get

    下面是完整的代碼和運行的結果。
it

結果:

wKioL1c9hLrx1XaAAAAKuzPkpm8071.png

    能夠看到上面的是最初的迷宮,通過咱們走迷宮的過程,將走過的岔路標記爲了3,正確的通路標記爲了2。


    完整代碼:

#define _CRT_SECURE_NO_WARNINGS 1

#include<iostream>
#include<assert.h>
#include<stack>
using namespace std;

struct Pos
{
	size_t line;
	size_t row;
};

void InitMaze(int *maze)
{
	FILE *p = fopen("maze.txt", "r");
	for (int i = 0; i < 10; i++)
	{
		for (int j = 0; j < 10;)
		{
			int tmp =(int)(fgetc(p))-'0';
			if (tmp == 0)
				maze[i*10+j] = 0;

			if (tmp == 1)
				maze[i*10+j] = 1;

			if (tmp == 1 || tmp == 0)
				j++;
		}
	}

	fclose(p);
}

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

int GoMaze(int *maze,Pos start)
{
	assert(maze);
	stack<int> p;
	
	Pos pos;
	pos.line = start.line;
	pos.row = start.row;

	while (1)
	{
		maze[(pos.line * 10 + pos.row)] = 2;

		if (pos.row>0 && maze[pos.line * 10 + pos.row - 1] == 1)//左
		{
			p.push(pos.line * 10 + pos.row);
			pos.row--;
			maze[(pos.line * 10 + pos.row)] = 2;
		}
		else if (pos.row < 9 && maze[pos.line * 10 + pos.row + 1] == 1)//右
		{
			p.push(pos.line * 10 + pos.row);
			pos.row++;
			maze[(pos.line * 10 + pos.row)] = 2;
		}
		else if (pos.line > 0 && maze[(pos.line - 1) * 10 + pos.row] == 1)//上
		{
			p.push(pos.line * 10 + pos.row);
			pos.line--;
			maze[(pos.line * 10 + pos.row)] = 2;
		}
		else if (pos.line < 9 && maze[(pos.line + 1) * 10 + pos.row] == 1)//下
		{
			p.push(pos.line * 10 + pos.row);
			pos.line++;
			maze[(pos.line * 10 + pos.row)] = 2;
		}
		else
		{
			maze[(pos.line * 10 + pos.row)] = 3;
			pos.line = p.top() / 10;
			pos.row = p.top() - pos.line*10;
			p.pop();
		}

		if (pos.line * 10 + pos.row == 91)
		{
			PrintMaze(maze);
			return 1;
		}
	}	
}

void Mazetest()
{
	int maze[10][10];
	Pos p;
	p.line = 2;
	p.row = 0;
	InitMaze((int *)maze);
	PrintMaze((int *)maze);
	GoMaze((int *)maze,p);
}

int main()
{
	Mazetest();
	return 0;
}
相關文章
相關標籤/搜索