简体   繁体   English

使用迷宫求解程序回溯逻辑错误

[英]Backtracking logic error with maze solving program

I've written a simple recursive maze solving problem that uses recursion to find the least number of moves to solve. 我已经编写了一个简单的递归迷宫解决问题,该问题使用递归来找到最少要解决的动作。 However, at dead ends, the program has trouble backing up the traced path. 但是,程序死胡同,无法备份跟踪的路径。

To try to solve the problem, I started to write inverse functions of the move functions. 为了解决该问题,我开始编写移动函数的逆函数。 They could be used to reverse the path, but would still need some way to identify which one to use. 它们可以用来反转路径,但是仍然需要某种方式来标识要使用的路径。

Maze test file: 迷宫测试文件:

SWWWW
OOOOE
OWOWW
OOOWW

Code body: 代码体:

//Read in maze
ifstream mazeFile;
mazeFile.open("MazeSample.txt");

vector<string> mazeRead{ istream_iterator<string>(mazeFile), istream_iterator<string>() };
maze = mazeRead;


    //Move checks
vector<string> maze;
int numMoves;
int leastMoves = 1000;

int row;
int column;

bool canMoveUp(int row, int column) {
    try {
        if (maze.at(row - 1).at(column) != ('O')) {
            cout << "(Can't move up)" << endl;
            if (maze.at(row - 1).at(column) == 'E') {
                return true;
            }
            return false;
        }
    }
    catch (const out_of_range& error) {
        cout << "(Can't move up)" << endl;
        return false;
    }
    return true;
}

bool canMoveDown(int row, int column) {
    try {
        if (maze.at(row + 1).at(column) != ('O')) {
            cout << "(Can't move down)" << endl;
            if (maze.at(row + 1).at(column) == 'E') {
                return true;
            }
            return false;
        }
    }
    catch (const out_of_range& error) {
        cout << "(Can't move down)" << endl;
        return false;
    }
    return true;
}

bool canMoveLeft(int row, int column) {
    try {
        if (maze.at(row).at(column - 1) != ('O')) {
            cout << "(Can't move left)" << endl;
            if (maze.at(row).at(column - 1) == 'E') {
                return true;
            }
            return false;
        }
    }
    catch (const out_of_range& error) {
        cout << "(Can't move left)" << endl;
        return false;
    }
    return true;
}

bool canMoveRight(int row, int column) {
    try {
        if (maze.at(row).at(column + 1) != ('O')) {
            cout << "(Can't move right)" << endl;
            if (maze.at(row).at(column + 1) == 'E') {
                return true;
            }
            return false;
        }
    }
    catch (const out_of_range& error) {
        cout << "(Can't move right)" << endl;
    }
    return true;
}


    //Maze solve function
void solve(int row, int column) {
    numMoves = numMoves + 1; //count moves

    //Base case (solution found; current position is 'E')
    if (maze[row][column] == 'E') {
        if (numMoves < leastMoves) {
            leastMoves = numMoves;
        }
    }

    if (maze[row][column] != 'E') {
        maze[row][column] = 't'; //mark path
    }

    // move up and see if move leads to solution (recursively)
    if (canMoveUp(row, column)) {
        cout << "(Move up)" << endl;
        row = row - 1;
        column = column;
        solve(row, column);
    }

    // if move chosen above doesn't lead to solution, move down & check
    if (canMoveDown(row, column)) {
        cout << "(Move down)" << endl;
        row = row + 1;
        column = column;
        solve(row, column);
    }

    // if move chosen above doesn't lead to solution, move left & check
    if (canMoveLeft(row, column)) {
        cout << "(Move left)" << endl;
        row = row;
        column = column - 1;
        solve(row, column);
    }

    // if move chosen above doesn't lead to solution, move right & check
    if (canMoveRight(row, column)) {
        cout << "(Move right)" << endl;
        row = row;
        column = column + 1;
        solve(row, column);
    }

    // if no above solution works, then unmark cell
    //backtrack (keeps going until all solutions reached)
    maze[row][column] = 'O';
    cout << "Mark as 'O'";
    numMoves = numMoves - 1;


    //TODO: PROBLEM: ROW/COLUMN NOT RESET AFTER STUCK; KEEPS SAME VALUE
            //Questionable code
    if (!canMoveUp(row, column)) {
        //Inverse of canMove?
        row = row + 1;
        column = column;
    }


    //Display vector contents
    cout << endl;
    for (int row = 0; row < maze.size(); row++) {
        cout << endl;
        for (int column = 0; column < maze[row].size(); column++) {
            cout << maze[row][column];
        }
    }
    cout << endl;
}

When hitting a dead end, I expected the maze to back up to the last junction with movement options. 当走到尽头时,我希望迷宫能回到运动选项的最后一个交界处。 Instead, the cursor goes back and forth, failing to solve. 而是,光标来回移动,无法解决。 This is likely due to the implementation of the move functions; 这可能是由于执行了移动功能所致; if able to move, it sets the row/column variables to the new space. 如果能够移动,它将行/列变量设置为新的空间。

The error path appears as follows, toggling itself between 't' and 'O' at row 1, column 1: 错误路径如下所示,在第1行第1列的't'和'O'之间切换:

SWWWW
tttOE
tWtWW
tttWW

SWWWW
tOtOE
tWtWW
tttWW

Upon not being able to move in any of the four directions, I'd expect the code to undo the previous movement(s) until reaching the last junction. 在无法在四个方向中的任何一个上移动时,我希望代码撤消之前的移动,直到到达最后一个结点。

Without looking too deep into your algorithm 无需深入了解您的算法

if (canMoveUp(row, column)) {
    cout << "(Move up)" << endl;
    row = row - 1;
    column = column;
    solve(row, column);
}

looks fishy. 看起来很腥。 You are changing the variables row and column that you are using in subsequent blocks. 您正在更改在后续块中使用的变量rowcolumn If canMoveUp is true, the next check will be canMoveDown('originalrow' - 1, column) which will fail (because it adds 1 to the row again and checks the field you just marked with t . 如果canMoveUp为true,则下一个检查将为canMoveDown('originalrow' - 1, column) ,该操作将失败(因为它将再次添加1到该行并检查刚刚标记为t的字段)。

Shouldn't it be 不是吗

if (canMoveUp(row, column)) {
    cout << "(Move up)" << endl;
    solve(row - 1, column);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM