[英]Solve a maze backtracking
I am trying to solve a maze using backtracking in C. To solve the maze the following rules:我正在尝试使用 C 中的回溯解决迷宫。要解决迷宫,请遵循以下规则:
The input consists of amxn matrix: Input example:输入由 amxn 矩阵组成: 输入示例:
11 11
+-+-+-+-+-+
S.|...|...|
+.+.+.+-+.+
|.|.|.....|
+.+-+-+-+.+
|...|.|...|
+.+.+.+.+-+
|.|...|.|.|
+.+-+.+.+.+
|...|.....E
+-+-+-+-+-+
Expected solution :预期的解决方案:
+-+-+-+-+-+
##|...|...|
+#+.+.+-+.+
|#|.|.....|
+#+-+-+-+.+
|###|.|...|
+.+#+.+.+-+
|.|###|.|.|
+.+-+#+.+.+
|...|######
+-+-+-+-+-+
I am trying really hard to solve it but for some reason my program doesn't go back once I reached a point in the maze from where I can't go further.It just go in all the directions where it sees a '.'我真的很努力地试图解决它,但由于某种原因,一旦我到达迷宫中的某个点,我就无法再继续下去,我的程序就不会返回。它只是朝着它看到“。”的所有方向前进。
My idea was to start from the position of S and using at each recursion step the old position that we were.我的想法是从 S 的位置开始,并在每个递归步骤中使用我们所在的旧位置。 I will go in all the direction from the position where I am standing if the position that I am looking at is a '.'
如果我正在看的位置是“.”,我将从我站立的位置向所有方向走。 and if that point was not my old position.
如果那一点不是我的旧立场。
I also think that I have a problem when i reach a point where it was a crossroad when I backtrack.我也认为当我到达一个十字路口时我有一个问题,当我回溯时。 For example:
例如:
+-+-+-+-+-+
##|...|...|
+#+.+.+-+.+
|#|.|.....|
+#+-+-+-+.+
|0##|.|...|
+.+#+.+.+-+
|.|###|.|.|
+.+-+#+.+.+
|..1|######
+-+-+-+-+-+
Imagine that I am in the position 0. And I backtracked from 1 changing back the # into '.'.How can I make a statement saying that you have 2 # possibilities to go back , yet you should stop?想象一下,我在位置 0。我从 1 回溯,将 # 改回 '.'。我怎么能声明说你有 2 # 种返回的可能性,但你应该停下来?
My code :我的代码:
#include <stdio.h>
#include <stdlib.h>
void *safeMalloc(int n) {
void *p = malloc(n);
if (p == NULL) {
printf("Error: malloc(%d) failed. Out of memory?\n", n);
exit(EXIT_FAILURE);
}
return p;
}
char ** readMatrix(int m,int n,int* startI,int* startJ,int* endI,int* endJ){
char **arr = safeMalloc(m*sizeof(char *));
int row;
for (row=0; row < m; row++) {
arr[row] = safeMalloc(n*sizeof(char));
}
int i,j;
for(i=0;i<m;i++){
for(j=0;j<m;j++){
scanf(" %c",&arr[i][j]);
if(arr[i][j]=='S'){
*startI=i;
*startJ=j;
}
if(arr[i][j]=='E'){
*endI=i;
*endJ=j;
}
}
getchar();
}
return arr;
}
void printNumber(char **arr,int m,int n){
int i,j;
for(i=0;i<m;i++){
for(j=0;j<n;j++){
printf("%c", arr[i][j]);
}
printf("\n");
}
}
void findPath(char** arr,int m,int n,int startI,int startJ,int endI,int endJ,int oldI,int oldJ){
int i=startI,j=startJ;
int stepsPossible=4;
//going up
if(i-1>=0){
if((arr[i-1][j]=='.') && ((i-1!=oldI) || (j!=oldJ))){
arr[i][j]='#';
oldI=i;
oldJ=j;
findPath(arr,m,n,i-1,j,endI,endJ,oldI,oldJ);
}else{
stepsPossible--;
}
}
//going right
if(j+1<n){
if((arr[i][j+1]=='.') && ((i!= oldI) || (j+1!=oldJ))){
arr[i][j]='#';
oldI=i;
oldJ=j;
findPath(arr,m,n,i,j+1,endI,endJ,oldI,oldJ);
}else{
stepsPossible--;
}
}
//going left
if(j-1>=0){
if((arr[i][j-1]=='.') && ((i!= oldI) || (j-1!=oldJ))){
arr[i][j]='#';
oldI=i;
oldJ=j;
findPath(arr,m,n,i,j-1,endI,endJ,oldI,oldJ);
}else{
stepsPossible--;
}
}
//going down
if(i+1<m){
if((arr[i+1][j]=='.') && ((i+1!= oldI) || (j!=oldJ))){
arr[i][j]='#';
oldI=i;
oldJ=j;
findPath(arr,m,n,i+1,j,endI,endJ,oldI,oldJ);
}else{
stepsPossible--;
}
}
//if the next block is E then we can stop.
if((arr[i-1][j]=='E') || (arr[i][j+1]=='E') || (arr[i][j-1]=='E') || (arr[i+1][j]=='E')){
if(arr[i-1][j]=='E'){
arr[i-1][j]='#';
}
if(arr[i][j+1]=='E'){
arr[i][j+1]='#';
}
if(arr[i][j-1]=='E'){
arr[i][j-1]='#';
}
if(arr[i+1][j]=='E'){
arr[i+1][j]='#';
}
return;
}
if(stepsPossible==0){
if(arr[i-1][j]=='#'){
arr[i][j]='.';
oldI=i;
oldJ=j;
findPath(arr,m,n,i-1,j,endI,endJ,oldI,oldJ);
}else{
return;
}
if(arr[i][j+1]=='#' ){
arr[i][j]='.';
oldI=i;
oldJ=j;
findPath(arr,m,n,i,j+1,endI,endJ,oldI,oldJ);
}else{
return;
}
if(arr[i][j-1]=='#' ){
arr[i][j]='.';
oldI=i;
oldJ=j;
findPath(arr,m,n,i,j-1,endI,endJ,oldI,oldJ);
}else{
return;
}
if(arr[i+1][j]=='#' ){
arr[i][j]='.';
oldI=i;
oldJ=j;
findPath(arr,m,n,i+1,j,endI,endJ,oldI,oldJ);
}else{
return;
}
}
}
int main()
{
int m,n;
scanf("%d %d",&m,&n);
int startI,startJ,endI,endJ;
char** arr;
arr=readMatrix(m,n,&startI,&startJ,&endI,&endJ);
findPath(arr,m,n,startI,startJ,endI,endJ,startI,startJ);
printNumber(arr,m,n);
return 0;
}
I would suggest to use BFS because我建议使用 BFS 因为
Here is short description of BFS for your case:以下是针对您的案例的 BFS 的简短描述:
Make proper use of the return value, as you can utilize it to simplify your logic.正确使用返回值,因为您可以利用它来简化您的逻辑。 Choose different return values on
findPath
for the error case (backtracking necessary) and the success case (end reached).在
findPath
为错误情况(需要回溯)和成功情况(到达终点)选择不同的返回值。
Now you can put setting the #
unconditionally in the start of that function, and resetting back to .
现在,您可以将
#
无条件地设置在该函数的开头,然后重新设置回.
unconditionally in the end for the backtracking case.无条件地在回溯的情况下结束。
There is no need to count possible directions either, only checking if some call returned success.也不需要计算可能的方向,只检查某个调用是否返回成功。
Also no need to write the boundary checks over and over again, if you just check them at the start of the function you can just pass invalid coordinates without any issues.也无需一遍又一遍地编写边界检查,如果您只是在函数开始时检查它们,则可以传递无效坐标而不会出现任何问题。
bool findPath(char** arr, size_t sx, size_t sy, int x, int y) {
if (x < 0 || x >= sx || y < 0 || y >= sy) return false;
if (arr[x][y] == 'E') {
are[x][y] = '#';
return true;
}
if (arr[x][y] != '.') return false;
arr[x][y] = '#';
bool success = findPath(arr, sx, sy, x-1, y) ||
findPath(arr, sx, sy, x+1, y) ||
findPath(arr, sx, sy, x, y-1) ||
findPath(arr, sx, sy, x, y+1);
if (!success) arr[x][y] = '.';
return success;
}
Implementations for backtracking algorithms usually all follow the same pattern:回溯算法的实现通常都遵循相同的模式:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.