// Oldham, Jeffrey D. // 1999 Oct 12 // CS 1320 // // ASCII Art Program // This is an interactive program that queries the user for the shape // to draw, adds it to the drawing being built, and displays the // drawing (using ASCII characters) upon demand. //****************************************************************************** // DECLARATIONS #include #include // has min() // Each function's pre- and postconditions appear before its // definition. // Command Processing Functions // Each drawing commands calls one of the following functions. The // function asks the user for the object's location and dimensions and // draws a geometric object. void doPoint(void); void doHorizontalLine(void); void doVerticalLine(void); void doSquare(void); void doFilledSquare(void); void doRectangle(void); void doFilledRectangle(void); // These functions draw a geometric object with the given parameters. void drawHorizontalLine(const int col, const int row, const int length, const char c); void drawVerticalLine(const int col, const int row, const int height, const char c); void drawRectangle(const int ulColumn, const int ulRow, const int length, const int height, const char c); void drawFilledRectangle(const int ulColumn, const int ulRow, const int length, const int height, const char c); // Helper Functions // These functions might be useful in implementing the command // processing functions. int obtainInteger(const char msg[], const int minValue, const int maxValue); char obtainCharacter(const char geometricObject[]); // Screen Declarations and Functions const int nuRows = 24; const int nuColumns = 80; void clearDrawing(void); void drawCharacter(const int column, const int row, const char ch); void printDrawing(void); //****************************************************************************** // PLACE FOR ADDITIONAL DECLARATIONS // // If you MUST add additional code, place any associated declarations here. //****************************************************************************** // THE MAIN PROGRAM int main() { char c; // command to run char promptString[] = "Please enter a command:\n" "\tp for a point\n" "\th for a horizontal line\n" "\tv for a vertical line\n" "\ts for a square\n" "\tS for a filled square\n" "\tr for a rectangle\n" "\tR for a filled rectangle\n" "\tP to print the drawing\n" "\te to erase the drawing\n" "\tq to quit\n" "\tcommand: "; clearDrawing(); clog << promptString; while (cin >> c && c != 'q') { if (c == 'p') doPoint(); else if (c == 'h') doHorizontalLine(); else if (c == 'v') doVerticalLine(); else if (c == 's') doSquare(); else if (c == 'S') doFilledSquare(); else if (c == 'r') doRectangle(); else if (c == 'R') doFilledRectangle(); else if (c == 'P') printDrawing(); else if (c == 'e') clearDrawing(); else cerr << "Unrecognized command character " << c << ".\n"; clog << promptString; } cerr << endl; // mostly useless except when saving clog << endl; // drawing to a file return 0; } //****************************************************************************** // THE COMMAND PROCESSING FUNCTIONS // precondition: none // postcondition: the user-specified character is written to the // user-specified position void doPoint(void) { int column = obtainInteger("point's column", 0, nuColumns); int row = obtainInteger("point's row", 0, nuRows); char ch = obtainCharacter("point"); drawCharacter(column, row, ch); return; } // precondition: none // postcondition: the user-specified character is written to the // user-specified horizontal line // The line is specified by its left point and its length. void doHorizontalLine(void) { // STILL TO BE IMPLEMENTED return; } // precondition: none // postcondition: the user-specified character is written to the // user-specified vertical line // The line is specified by its upper point and its height. void doVerticalLine(void) { // STILL TO BE IMPLEMENTED return; } // precondition: none // postcondition: the user-specified character is written to the // user-specified square // The square is specified by its upper left point and the // length of a side. void doSquare(void) { // STILL TO BE IMPLEMENTED return; } // precondition: none // postcondition: the user-specified character is written to the // user-specified square which is filled in // The square is specified by its upper left point and the // length of a side. void doFilledSquare(void) { // STILL TO BE IMPLEMENTED return; } // precondition: none // postcondition: the user-specified character is written to the // user-specified rectangle // The rectangle is specified by its upper left point, its height, // and its width. void doRectangle(void) { // STILL TO BE IMPLEMENTED return; } // precondition: none // postcondition: the user-specified character is written to the // user-specified rectangle // The rectangle is specified by its upper left point, its height, // and its width. void doFilledRectangle(void) { // STILL TO BE IMPLEMENTED return; } //****************************************************************************** // THE DRAWING FUNCTIONS // precondition: line's origin = (col, row) // line's length // postcondition: the specified horizontal line is drawn void drawHorizontalLine(const int col, const int row, const int length, const char c) { // STILL TO BE IMPLEMENTED return; } // precondition: line's origin = (col, row) // line's height // postcondition: the specified vertical line is drawn void drawVerticalLine(const int col, const int row, const int height, const char c) { // STILL TO BE IMPLEMENTED return; } // precondition: rectangle's upper left corner = (ulColumn, ulRow) // length, height = its length and height // postcondition: the specified rectangle's outline is drawn void drawRectangle(const int ulColumn, const int ulRow, const int length, const int height, const char c) { drawHorizontalLine(ulColumn, ulRow, length, c); drawHorizontalLine(ulColumn, ulRow+height-1, length, c); drawVerticalLine(ulColumn, ulRow, height, c); drawVerticalLine(ulColumn+length-1, ulRow, height, c); return; } // precondition: filled rectangle's upper left corner = (ulColumn, ulRow) // length, height = its length and height // postcondition: the specified rectangle is drawn, filled in void drawFilledRectangle(const int ulColumn, const int ulRow, const int length, const int height, const char c) { // STILL TO BE IMPLEMENTED return; } //****************************************************************************** // HELPER FUNCTIONS // precondition: msg = message prompting for a desired value // minValue = minimum acceptable input // maxValue = maximum acceptable input // postcondition: returns a user-specified integer value in the range // [minValue,maxValue) int obtainInteger(const char msg[], const int minValue, const int maxValue) { if (minValue == maxValue - 1) return minValue; else { int c; char ignoredChar; bool goodInput = false; do { clog << "Please enter the " << msg << " [" << minValue << "," << maxValue << "): "; if (cin >> c) { if (c >= minValue && c < maxValue) goodInput = true; else cerr << "The " << msg << " must be in the range [" << minValue << "," << maxValue << ").\n"; } else { cerr << "Please enter an integer!\n"; if (cin.eof()) // received Control-D! cin.clear(); else { // received a non-integer cin.clear(); cin.get(ignoredChar); } } } while (!goodInput); return c; } } // precondition: the given string indicates the geometric object // postcondition: returns the user-specified character char obtainCharacter(const char geometricObject[]) { char ch; clog << "Please enter the " << geometricObject << "'s character: "; cin >> ch; return ch; } //****************************************************************************** // CONVERTING FROM TWO TO ONE DIMENSION: an Abstraction Barrier // Conceptually, the ASCII drawing is a two-dimensional array with // upper left corner at (0,0) and lower right corner at (nuColumns, // nuRows). // We implement this drawing as a one-dimensional array, storing one // row after another. Thus, the first nuColumns characters are in the // first row, the next nuColumns characters are in the second row, // etc. // To change the drawing, use the drawCharacter() function to place a // character at a specified (column, row) position. // To print the drawing in its current state, use the printDrawing() // function. // To clear the drawing, use the clearDrawing() function. // the drawing char oneDimensionScreen[nuRows * nuColumns]; // Erase the drawing's contents. void clearDrawing(void) { for (int row = 0; row < nuRows; ++row) for (int column = 0; column < nuColumns; ++column) drawCharacter(column, row, ' '); return; } // Place a character at the specified location. // Silently ignore illegal row and column values. void drawCharacter(const int column, const int row, const char ch) { if (column < 0 || column >= nuColumns || row < 0 || row >= nuRows) return; oneDimensionScreen[row * nuColumns + column] = ch; return; } // Print the drawing. void printDrawing(void) { for (int row = 0; row < nuRows; ++row) { for (int column = 0; column < nuColumns; ++column) cout << oneDimensionScreen[row * nuColumns + column]; cout << endl; } return; } //****************************************************************************** // PLACE FOR ADDITIONAL CODE // // If you must add additional code, put it here. Place the declarations // near the top of this file.