问题描述:实验心理学中的一个典型的问题,心理学家吧一只老鼠从一个无顶的大盒子的入口处赶进迷宫。迷宫设置很多隔壁,对前进方向形成了许多障碍,心理学家在迷宫的唯一出口处放置了一块奶酪,吸引老鼠仔迷宫中寻找通路以到达出口。

  求解思想:回溯法是一种不断试探且及时纠正错误的搜索方法,下面的求解过程采用回溯法。从入口出发,按某一方向向前探索,若能走通(未走过的),即某处可以到达,则到达一个新点,否则试探下一个方向;若所有的方向均没有通路,则沿原路返回前一点,换下一个方向继续试探,直到所有可能的通路都搜索到,或找到一条通路,或无路可走又返回到入口点。这里可以用一个栈来实现,每走一步,将该位置压入栈中,若该点无路可走,则出栈返回上一位置。

  需要解决的四个问题:

  (1)表示迷宫的数据结构

  设迷宫为m行n列,利用数组maze[m][n]来表示一个迷宫,maze[i][j]=0或1,其中0表示通路,1表示不通,2 表示已走过。迷宫该数组四边都为1,代表迷宫四周都是墙。这样就可以保证每个点都有8个方向可以试探。

  入口为(1,1),出口为(6,8)

  1,1,1,1,1,1,1,1,1,1
      0,0,1,1,1,0,1,1,1,1
      1,1,0,1,0,1,1,1,1,1
      1,0,1,0,0,0,0,0,1,1
      1,0,1,1,1,0,1,1,1,1
      1,1,0,0,1,1,0,0,0,1
      1,0,1,1,0,0,1,1,0,1
      1,1,1,1,1,0,1,1,1,1

代码如下:

#define _CRT_SECURE_NO_WARNINGS 1
#pragma once
#include<stack>
#include<assert.h>

#define N  10
#include<iostream>
using namespace std;

struct pos  //坐标点
{
	int _row;  //行
	int _col;   //列
};

void GetMaze(int* a, int n)   //从文件中读取数据,存储在数组中
{
	assert(a);
	FILE* fout = fopen("E:\\比特科技编程\\数据结构\\迷宫实现\\maze.txt", "r");
	assert(fout);
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < n;)
		{
			char ch = fgetc(fout);
			if (ch == '1' || ch == '0')
			{
				a[i * n + j] = ch - '0';
				j++;
			}
			else
			{
				continue;
			}
		}
	}
	fclose(fout);
}

bool CheckisAccess(int *a, int n, const pos& next)  //判断是否可以前进
{
	int row = next._row;
	int col = next._col;
	if (row >= 0 && row < n&&col >= 0 && col < n&&a[next._row*n + next._col] == 0)
	{
		return true;
	}
	else
	{
		return false;
	}
}

bool searchpath(int* a, int n, pos entry, stack<pos>& paths)
{
	assert(a);
	paths.push(entry);
	while (!paths.empty())  //如果栈为空,就没找到出口
	{
		pos cur = paths.top();
		a[cur._row*n + cur._col] = 2;
		if (cur._row == n - 1 ||cur._col==n-1)
		{
			return true;
		}
		pos next = cur;
		next._row--;//向上搜索
		if (CheckisAccess(a, n, next))
		{
			cur = next;
			paths.push(cur);
			continue;
		}

		next = cur;
		next._col++;//向右搜索
		if (CheckisAccess(a, n, next))
		{
			cur = next;
			paths.push(cur);
			continue;
		}
		next = cur;
		next._row++;//向下搜索
		if (CheckisAccess(a, n, next))
		{
			cur = next;
			paths.push(cur);
			continue;
		}
		next = cur;
		next._col--;// 向左搜索
		if (CheckisAccess(a, n, next))
		{
			cur = next;
			paths.push(cur);
			continue;
		}
		//	next = cur;
		paths.pop();  //如果没有出路,则出栈,原路返回
	}

	return false;
}
void display(int* a, int n)    //打印迷宫
{
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < n; j++)
		{
			cout << a[i*n + j] << " ";
		}
		cout << endl;
	}

}

测试代码如下:

#include"MazeMap.h"
#include<stdio.h> 


void test()
{
	int a[N][N];
	GetMaze((int*)a, N);
	stack<pos> paths;   //定义栈
	pos entry = { 2, 0 }; // 调用入口
	cout << searchpath((int*)a, N, entry, paths) << endl;
	display((int*)a, N);
}
int main()
{
	test();
	system("pause");
	return 0;
}