我们正在编写一个迷宫解决方案,作为初学者小组项目。
我的队友创建了异常处理部分。
具有讽刺意味的是,使用其异常处理模块运行程序会产生“异常未处理”错误:
“引发未处理的异常:读取访问冲突。此-> 迷宫 是0x1110112。发生了
它指向Maze.cpp中的第124行
while (amaze[x][y] != 'F')
我已经本地化了错误的根源: 如果我更改Maze.cpp中的第57行:
if (temp != 'X' && temp != 'F' && temp != ' ')
到
if(1)
然后它可以正常工作,但是我不明白为什么。有人可以解释吗?
主要
#include <cstdlib>
#include <iostream>
#include "Maze.h"
using namespace std;
int main(int argc, char* argv[])
{
#define OPEN ' '
#define WALL 'X'
#define FINISH 'F'
cout << "Program START" << endl << endl;
const int rows1 = 10;
const int cols1 = 10;
char maze1[rows1][cols1] = {
{OPEN, WALL, OPEN, WALL, OPEN, WALL, OPEN, WALL, OPEN, WALL},
{OPEN, WALL, OPEN, WALL, OPEN, WALL, OPEN, WALL, OPEN, WALL},
{OPEN, OPEN, OPEN, WALL, OPEN, WALL, OPEN, WALL, OPEN, WALL},
{OPEN, WALL, OPEN, WALL, OPEN, WALL, OPEN, WALL, OPEN, WALL},
{OPEN, WALL, OPEN, WALL, OPEN, WALL, OPEN, WALL, OPEN, WALL},
{OPEN, WALL, OPEN, OPEN, OPEN, WALL, OPEN, WALL, OPEN, FINISH},
{OPEN, WALL, OPEN, WALL, OPEN, WALL, OPEN, OPEN, OPEN, WALL},
{OPEN, WALL, OPEN, WALL, OPEN, WALL, OPEN, WALL, OPEN, WALL},
{OPEN, WALL, OPEN, WALL, OPEN, OPEN, OPEN, WALL, OPEN, WALL},
{OPEN, WALL, OPEN, WALL, OPEN, WALL, OPEN, WALL, OPEN, WALL}
};
//////////////////////////////////////////////////////////////////////////////
// Very clumsy way to allow for variable rows and columns, for now.
char *b1[cols1];
for (int r = 0; r < rows1; r++)
b1[r] = maze1[r];
maze1[4][5] = 'C';
char *b4 = nullptr;
Maze game;
try {
game.set_maze(b1, rows1, cols1);
}
catch (const char *msg)
{
cout << "Error: " << msg << endl;
}
try {
game.set_maze(NULL, rows1, cols1);
}
catch (const char *msg)
{
cout << "Error: " << msg << endl;
}
try {
game.set_maze(&b4, rows1, cols1);
}
catch (const char *msg)
{
cout << "Error: " << msg << endl;
}
try {
game.set_maze(b1, -1, 10);
}
catch (const char *msg)
{
cout << "Error: " << msg << endl;
}
try {
game.set_maze(b1, rows1, -10);
}
catch (const char *msg)
{
cout << "Error: " << msg << endl;
}
game.print(); // Make sure its right.
bool solved = game.solve_with_vector();
if (solved == true) cout << "YEAH! solved with vector!\n";
else cout << "BOO! can't solve with vector!\n";
game.print();
//////////////////////////////////////////////////////////////////////////////
// Another solvable maze alternative to the starter version
const int rows2 = 16;
const int cols2 = 20;
char maze2[rows2][cols2] = {
{OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN},
{OPEN, WALL, WALL, WALL, WALL, OPEN, WALL, WALL, WALL, WALL, WALL, WALL, WALL, WALL, OPEN, WALL, WALL, WALL, WALL, OPEN},
{OPEN, WALL, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, WALL, OPEN},
{OPEN, WALL, OPEN, WALL, WALL, WALL, WALL, WALL, WALL, WALL, WALL, WALL, WALL, WALL, WALL, WALL, WALL, OPEN, WALL, OPEN},
{OPEN, WALL, OPEN, WALL, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, WALL, OPEN, WALL, OPEN},
{OPEN, WALL, OPEN, WALL, OPEN, WALL, WALL, WALL, WALL, WALL, OPEN, WALL, WALL, WALL, WALL, OPEN, WALL, OPEN, WALL, OPEN},
{OPEN, OPEN, OPEN, WALL, OPEN, WALL, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, WALL, OPEN, WALL, OPEN, WALL, OPEN},
{OPEN, WALL, OPEN, WALL, OPEN, OPEN, OPEN, WALL, WALL, FINISH, WALL, WALL, OPEN, OPEN, WALL, OPEN, WALL, OPEN, WALL, OPEN},
{OPEN, WALL, OPEN, WALL, OPEN, WALL, OPEN, WALL, WALL, WALL, WALL, WALL, OPEN, OPEN, WALL, OPEN, WALL, OPEN, OPEN, OPEN},
{OPEN, WALL, OPEN, WALL, OPEN, WALL, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, WALL, OPEN, WALL, OPEN, WALL, OPEN},
{OPEN, WALL, OPEN, WALL, OPEN, WALL, WALL, WALL, OPEN, WALL, WALL, WALL, WALL, WALL, WALL, OPEN, WALL, OPEN, WALL, OPEN},
{OPEN, WALL, WALL, WALL, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, WALL, OPEN},
{OPEN, WALL, OPEN, WALL, WALL, OPEN, WALL, WALL, WALL, WALL, WALL, WALL, WALL, WALL, WALL, WALL, WALL, OPEN, WALL, OPEN},
{OPEN, WALL, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, WALL, OPEN},
{OPEN, WALL, WALL, WALL, WALL, WALL, WALL, WALL, WALL, OPEN, WALL, WALL, WALL, WALL, WALL, WALL, WALL, WALL, WALL, OPEN},
{OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN, OPEN}
};
//////////////////////////////////////////////////////////////////////////////
// Very clumsy way to allow for variable rows and columns, for now.
char *b2[cols2];
for (int r = 0; r < rows2; r++)
b2[r] = maze2[r];
Maze game2; // Do another solvable different size
game2.set_maze(b2, rows2, cols2);
game2.print();
solved = game2.solve_with_vector();
if (solved == true) cout << "YEAH! solved with vector!\n";
else cout << "BOO! can't solve with vector!\n";
game2.print();
//////////////////////////////////////////////////////////////////////////////
// This maze does not contain a finish so is unsolveable.
// Use to test whether you are actually traversing the whole maze.
// Output should be the maze with all open spaces changed to . (dots)
const int rows3 = 10;
const int cols3 = 10;
char maze3[rows3][cols3] = {
{OPEN, WALL, OPEN, WALL, OPEN, WALL, OPEN, WALL, OPEN, WALL},
{OPEN, WALL, OPEN, WALL, OPEN, WALL, OPEN, WALL, OPEN, WALL},
{OPEN, OPEN, OPEN, WALL, OPEN, WALL, OPEN, WALL, OPEN, WALL},
{OPEN, WALL, OPEN, WALL, OPEN, WALL, OPEN, WALL, OPEN, WALL},
{OPEN, WALL, OPEN, WALL, OPEN, WALL, OPEN, WALL, OPEN, WALL},
{OPEN, WALL, OPEN, OPEN, OPEN, WALL, OPEN, WALL, OPEN, WALL},
{OPEN, WALL, OPEN, WALL, OPEN, WALL, OPEN, OPEN, OPEN, WALL},
{OPEN, WALL, OPEN, WALL, OPEN, WALL, OPEN, WALL, OPEN, WALL},
{OPEN, WALL, OPEN, WALL, OPEN, OPEN, OPEN, WALL, OPEN, WALL},
{OPEN, WALL, OPEN, WALL, OPEN, WALL, OPEN, WALL, OPEN, WALL}
};
//////////////////////////////////////////////////////////////////////////////
// Very clumsy way to allow for variable rows and columns, for now.
char *b3[cols3];
for (int r = 0; r < rows3; r++)
b3[r] = maze3[r];
Maze game3; // Do an unsolvable
game3.set_maze(b3, rows3, cols3);
game3.print();
solved = game3.solve_with_vector();
if (solved == true) cout << "YEAH! solved with vector!\n";
else cout << "BOO! can't solve with vector!\n";
game3.print();
return 0;
}
Maze.cpp
#include <iostream>
#include <vector>
#include "Maze.h"
using namespace std;
// Constructor only initializes class variables.
Maze::Maze() {
rows = cols = 0;
amaze = NULL;
}
// Destructor doesn't have anything to do but is left as a place holder
// for any future features that need cleanup.
Maze::~Maze() {
// Nothing to get rid of since we just point to the users supplied maze.
}
// Attach a users maze. Keep track of number of rows and columns in it.
void Maze::set_maze(char ** maz, int numr, int numc) {
if (maz == nullptr)
{
throw "maz nullptr";
}
if (*maz == nullptr)
{
throw "*maz nullptr";
}
if (numr <= 0)
{
throw "rows must be positive value";
}
if (numc <= 0)
{
throw "columns must be positive value";
}
char temp = NULL;
for (int j = 0; j < numr; j++)
{
for (int k = 0; k < numc; k++)
{
temp = maz[j][k]; // Using a temp variable for code readability
if (temp != 'X' && temp != 'F' && temp != ' ')
{
//cout << "ivalid maze element (character) at [r],[c]: [" << j << "],[" << k << "]\n";
throw "ivalid maze element (character)";
}
}
}
rows = numr;
cols = numc;
amaze = maz;
}
// Determine if a row and column are inside the maze and
// not a wall nor already searched.
//
// Returns:
// true for open inside not searched.
// false if its outside, wall, already searched or finish.
//
bool Maze::check_if_open(int r, int c) {
// Any row or column that is negative is outside.
// Any row or column that is greater than the values passed to set_maze are outside.
if (r < 0 || c < 0 || r >= rows || c >= cols) { // Outside
return false;
}
// '.' is already searched, 'F' is the finish, 'S' is the start, 'X' is wall
// We only check for this so we can be sure that when we get to the end we have
// checked all valid possibilities.
if (amaze[r][c] == '.' || amaze[r][c] == 'X' || amaze[r][c] == 'S') { // not open
return false;
}
if (amaze[r][c] == ' ' || amaze[r][c] == 'F') { // open
return true;
}
// If we get here it is something unexpected so its an error.
cout << "Error: Unexpected state found in maze: " << amaze[r][c] << endl;
return false;
}
// YOUR COMMENTS GO HERE
bool Maze::solve_with_vector() {
class Alt // Nested Class for alternative route's coordinates
{
public:int x; int y;
};
vector<Alt> alt;
// Current position:
int x = 0; // current raw - Starting at (0,0) according to handout
int y = 0; // current column - Starting at (0,0) according to handout
alt.clear(); // Clear our vector of alternative paths
while (amaze[x][y] != 'F') // Loop until found Finish or ran out of alternative paths
{
amaze[x][y] = '.'; // Set current location to visited
if (check_if_open(x - 1, y) == true) // if neighbor up (amaze[row-1][col]) is open, push it
{
alt.push_back(Alt());
alt.back().x = x - 1;
alt.back().y = y;
}
if (check_if_open(x, y + 1) == true) // if neighbor right (amaze[row][col+1]) is open, push it
{
alt.push_back(Alt());
alt.back().x = x;
alt.back().y = y + 1;
}
if (check_if_open(x + 1, y) == true) // if neighbor down (amaze[row+1][col]) is open, push it
{
alt.push_back(Alt());
alt.back().x = x + 1;
alt.back().y = y;
}
if (check_if_open(x, y - 1) == true) // if neighbor left (amaze[row][col-1]) is open, push it
{
alt.push_back(Alt());
alt.back().x = x;
alt.back().y = y - 1;
}
if (alt.empty()) // if vector is empty, maze is unsolvable, so return false
{
return false;
} // else pop a path from the vector (i.e. reset current row and column from vector)
else
{
x = alt.back().x;
y = alt.back().y;
alt.pop_back();
}
}
return true; // If found "Finish", return true
}
// Print the current state of the maze.
// Maze if made up of chars where:
// ' ' is open,
// 'X' is wall,
// 'F' is finish,
// '.' is already searched
//
void Maze::print() {
for (int row = 0; row < rows; row++) {
for (int col = 0; col < cols; col++) {
cout << amaze[row][col] << " ";
}
cout << endl;
}
cout << endl;
}
Maze.h
#ifndef MAZE_H
#define MAZE_H
#include <iostream>
#include <vector>
using namespace std;
class Maze {
private:
char ** amaze; // The maze
int rows; // Number of rows in the maze
int cols; // Number of cols in the maze
bool check_if_open(int row, int col);
// Check if open (not wall, not outside, not already searched, not a finish ...)
bool finished(int row, int col);
public:
Maze(); // constructor
~Maze(); // destructor
void set_maze(char ** maz, int numr, int numc);
bool solve_with_vector(); // solves maze, alternate possible routes are saved in a vector
void print(); // prints current state of maze,
// ' ' is open, 'X' is wall, 'F' is finish, '.' is searched
};
#endif /* MAZE_H */