/////////////////////////////////////////////////////////// // // maze.cpp // // This class represents a rectangular maze. The input // operator >> supports a data format used to store // a maze in a text file. This file format is adapted from // a format described in the problem set for the 2000 // North Central Section of the ACM International Collegiate // Programming Contest. The file format is: // // Number of rows // Number of columns // For each row, each square in the row is // represented by a hexadecimal digit. // // The hexadecimal digits are obtained like this: // // Start with 0 // If the square has a top wall, add 1 // If the square has a right-hand wall, add 2 // If the square has a bottom wall, add 4 // If the square has a left-hand wall, add 8 // Write the resulting number (0-15) as a hexdecimal // digit (0-9, A, B, C, D, E, or F). // // For example, a 2x3 maze with exterior but no interior walls // (that is, an empty 2x3 room) would be represented by: // // 2 3 // 9 1 3 // C 4 6 // // You don't have to parse this file format--that's what // operator>> already does--but you might want to create // example mazes for testing. // Revision history: // 1/11/01 (Jeff Ondich) Two constructors, <<, and >>. // /////////////////////////////////////////////////////////// #include "maze.h" // Initialize maze to 0 rows, 0 columns. No place // for the Minotaur to hide. Maze::Maze() { mRows = 0; mColumns = 0; } // Read the maze from the Maze::Maze( const char *fileName ) { ifstream in( fileName ); if( !in.is_open() ) { cerr << "Can't open " << fileName << endl; exit(1); } in >> *this; in.close(); } // Reads from the input stream a maze described in // the format outlined in the comment at the top of // this file. istream& operator>>( istream& in, Maze& m ) { // Get the number of rows and columns. Protect // against out-of-range values. in >> m.mRows; in >> m.mColumns; if( m.mRows < 0 || m.mRows > kMaxRows ) m.mRows = 0; if( m.mColumns < 0 || m.mColumns > kMaxRows ) m.mColumns = 0; // Read the square values. for( int i=0; i < m.mRows; i++ ) { for( int j=0; j < m.mColumns; j++ ) { int squareValue; in >> hex >> squareValue; m.mSquare[i][j].mTop = ((squareValue & 1) != 0); m.mSquare[i][j].mRight = ((squareValue & 2) != 0); m.mSquare[i][j].mBottom = ((squareValue & 4) != 0); m.mSquare[i][j].mLeft = ((squareValue & 8) != 0); } } return( in ); } // Prints the maze to the output stream. X's are drawn // wherever the maze is inconsistent. (For example, if // m.mSquare[0][0].mRight is true (there's a wall) but // m.mSquare[0][1].mLeft is false (there's not a wall), // then the maze is messed up, and the printout shows // that fact. ostream& operator<<( ostream& out, Maze& m ) { int i, j; for( i=0; i < m.mRows; i++ ) { // Draw the top walls of this row of squares. out << '+'; for( j=0; j < m.mColumns; j++ ) { if( i > 0 && m.mSquare[i][j].mTop != m.mSquare[i-1][j].mBottom ) out << "xxx+"; else if( m.mSquare[i][j].mTop ) out << "---+"; else out << " +"; } out << endl; // Draw the left and right walls of this row of squares. if( m.mColumns > 0 && m.mSquare[i][0].mLeft ) out << '|'; else out << ' '; for( j=0; j < m.mColumns; j++ ) { if( j < m.mColumns - 1 && m.mSquare[i][j].mRight != m.mSquare[i][j+1].mLeft ) out << " X"; else if( m.mSquare[i][j].mRight ) out << " |"; else out << " "; } out << endl; } if( m.mRows > 0 ) { // Draw the bottom walls of the bottom row of squares. out << '+'; for( j=0; j < m.mColumns; j++ ) { if( m.mSquare[m.mRows-1][j].mBottom ) out << "---+"; else out << " +"; } out << endl; } return( out ); }