我正在编写一种算法,通过粘贴在墙上并按此顺序移动来找到通过迷宫的方法:向下 - 向右 - 向上 - 向左直到找到出口。但是,有时候,它会陷入无限循环而无法继续。我一直想弄清楚几个小时出了什么问题而我没有运气。这是代码
#include <iostream>
#include <windows.h>
const int MazeWidth = 30;
const int MazeHeight = 20;
const char MazeExit = '$';
const char Wall = '#';
const char Free = ' ';
const unsigned char SomeDude = 254;
COORD MazeExitCoords;
COORD StartingPoint;
using namespace std;
char Maze [MazeHeight][MazeWidth];
void FillDaMaze(){
MazeExitCoords.X = MazeWidth - 20;
MazeExitCoords.Y = 2;
StartingPoint.X = 3;
StartingPoint.Y = MazeHeight - 3;
for(int i = 0; i < MazeHeight; i++){
for(int ii = 0; ii < MazeWidth; ii++){
if(i == 0 || i == MazeHeight - 1 || ii == 0 || ii == MazeWidth - 1){
Maze[i][ii] = Wall;
}
else{
Maze[i][ii] = Free;
}
if(i == MazeExitCoords.Y && ii == MazeExitCoords.X){
Maze[i][ii] = MazeExit;
}
else if(i == StartingPoint.Y && ii == StartingPoint.X){
Maze[i][ii] = SomeDude;
}
}
}
}
void PrintDaMaze(int color){
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),color);
for(int i = 0; i < MazeHeight; i++){
for(int ii = 0; ii < MazeWidth;ii++){
cout << Maze[i][ii];
}
cout << endl;
}
}
void FindYourWayThroughTheMaze(){
if(Maze[StartingPoint.Y + 1][StartingPoint.X] != Wall && Maze[StartingPoint.Y + 1][StartingPoint.X ] != SomeDude){
StartingPoint.Y++;
}
else if(Maze[StartingPoint.Y][StartingPoint.X + 1] != Wall && Maze[StartingPoint.Y][StartingPoint.X + 1] != SomeDude){
StartingPoint.X++;
}
else if(Maze[StartingPoint.Y - 1][StartingPoint.X] != Wall && Maze[StartingPoint.Y - 1][StartingPoint.X ] != SomeDude){
StartingPoint.Y--;
}
else if(Maze[StartingPoint.Y][StartingPoint.X - 1] != Wall && Maze[StartingPoint.Y][StartingPoint.X - 1] != SomeDude){
StartingPoint.X--;
}
Maze[StartingPoint.Y][StartingPoint.X] = SomeDude;
}
int main(){
FillDaMaze();
PrintDaMaze(10);
while(StartingPoint.X != MazeExitCoords.X || StartingPoint.Y != MazeExitCoords.Y){
FindYourWayThroughTheMaze();
system("CLS");
PrintDaMaze(10);
Sleep(50);
}
}
答案 0 :(得分:20)
要有机会解决它,你必须:
Solve()
例程并递归调用自身:
Solve
已成功找到解决方案这是基于以上概念的粗略实现:
#include "stdafx.h"
#include <stdio.h>
const int MazeHeight = 9;
const int MazeWidth = 9;
char Maze[MazeHeight][MazeWidth + 1] =
{
"# #######",
"# # #",
"# ### # #",
"# # # #",
"# # # ###",
"# # # #",
"# ### # #",
"# # #",
"####### #",
};
const char Wall = '#';
const char Free = ' ';
const char SomeDude = '*';
class COORD
{
public:
int X;
int Y;
COORD(int x = 0, int y = 0) { X = x, Y = y; }
COORD(const COORD &coord) { X = coord.X; Y = coord.Y; }
};
COORD StartingPoint(1, 0);
COORD EndingPoint(7, 8);
void PrintDaMaze()
{
for (int Y = 0; Y < MazeHeight; Y++)
{
printf("%s\n", Maze[Y]);
}
printf("\n");
}
bool Solve(int X, int Y)
{
// Make the move (if it's wrong, we will backtrack later.
Maze[Y][X] = SomeDude;
// If you want progressive update, uncomment these lines...
//PrintDaMaze();
//Sleep(50);
// Check if we have reached our goal.
if (X == EndingPoint.X && Y == EndingPoint.Y)
{
return true;
}
// Recursively search for our goal.
if (X > 0 && Maze[Y][X - 1] == Free && Solve(X - 1, Y))
{
return true;
}
if (X < MazeWidth && Maze[Y][X + 1] == Free && Solve(X + 1, Y))
{
return true;
}
if (Y > 0 && Maze[Y - 1][X] == Free && Solve(X, Y - 1))
{
return true;
}
if (Y < MazeHeight && Maze[Y + 1][X] == Free && Solve(X, Y + 1))
{
return true;
}
// Otherwise we need to backtrack and find another solution.
Maze[Y][X] = Free;
// If you want progressive update, uncomment these lines...
//PrintDaMaze();
//Sleep(50);
return false;
}
int _tmain(int argc, _TCHAR* argv[])
{
if (Solve(StartingPoint.X, StartingPoint.Y))
{
PrintDaMaze();
}
else
{
printf("Damn\n");
}
return 0;
}
答案 1 :(得分:5)
正如Luchian已经发布的那样,算法(即使正确实施)也不适合找到各种迷宫中的方法:如果你的迷宫中有一些循环,你可能最终会绕着这个循环墙跑来跑去。
另外,看起来,你并没有真正产生一个迷宫,而是一个在边界处有墙壁并且在其内部某处有“出口”的大场。如果出口不靠近墙壁(目前只在“迷宫”的边界处),那么真正“贴墙”的算法将永远找不到出口。
由于你没有删除SomeDude
s,即你已经去过的职位,并且你正在以SomeDude
的方式对待Wall
,你就是用某种“SomeDude-Wall”慢慢填满迷宫:你向下走直到你撞到边界,然后在场地周围大逆时针旋转,留下SomeDude
s的痕迹。
根据您的起点和出口,您可以轻松地遇到所有四个方向被阻挡的情况,无论是通过“真实”墙还是您之前留下的SomeDude
。然后,四个if
- 语句中没有一个被执行,你只有一个无限循环(因为循环体内没有任何变化)。
对于一个算法,它会粘在一堵墙上(因而能够找到某种方法来解决某些类型的迷宫),我建议采取以下步骤:
SomeDude
- 跟踪),直到其中任何一个
通过这种方式,您确保右侧始终存在“相同”的墙壁,因此您“坚持”到该墙壁。
请记住,这个算法找不到出口,如果出口在一些自由空间内(因为它总是粘在墙上,出口也必须靠近墙壁才能找到)。
对于能够找到所有可能的迷宫的算法,你需要进行某种回溯:记住每个点,你有多个选择可以继续。选择一种方式,然后按照它。如果它是一个死胡同,请回到最后的决定点并采取下一个选择。如果没有办法通往出口,请转到上一个最后一点,依此类推。这是一种递归方法,在图论中被称为“深度优先搜索”(随意做一些谷歌搜索,我很自信,你会发现很多关于这个的材料:) ...)< / p>
HTH 马丁