#include #include #include #include #include #include #include #include // for accessing timing operations #include "Game.h" #include "ArrayGame.h" #include "LinkedGame.h" // #define PRINTTIME using namespace std; istream *isr; bool echoinput; bool endOfInput=false; string* GeneralQuestion(string* prompt) { string response; string *answer = &response; bool done = false; if (prompt) cout << *prompt; while (!done) { getline(*isr, response); if ((*isr).eof()) { // must be EOF if (echoinput) { // switch to keyboard input isr = &cin; echoinput=false; } else { cout << "unexpected end of input reached.\n"; endOfInput = true; answer = NULL; done=true; } } else { // successful so far if (echoinput) cout << response << "\n"; if ((response).length()>0) done=true; } } if (answer) { answer = new string(response); } return(answer); } bool valid(Game *g) { if (g==NULL) { cout << "The game has not yet been properly initialized.\n"; return(false); } else { return(true); } } int main(int argc, const char* argv[]) { string MENU = "Valid commands include:\n(A) create or reinitialize with ArrayGame.\n(L) create or reinitialize with LinkedGame.\n(S) call size.\n(P) call playRound.\n(C) call completeGame.\n(V) call toggleVerbose.\n(X) extra credit challenge.\n(Q) Quit."; filebuf fb; bool quit = false; int value, value2; int i; int command=1; string *response; string answer; char choice; bool arrayBased; Game *curGame = NULL; // choose between keyboard input or mock-keyboard file input echoinput = false; isr = &cin; if (argc>1) { fb.open(argv[1],ios::in); if (fb.is_open()) { isr = new istream(&fb); echoinput= true; } else { cout << "Input file '" << argv[1] << "' not found.\n"; cout << "Defaulting to keyboard input.\n\n"; } } // is there a limit on the number of lines to read? int LIMIT = -1; if (argc>2) { LIMIT = atoi(argv[2]); if (LIMIT < 1) { LIMIT = -1; cout << "Second argument (" << argv[2] << ") ignored.\n\n"; } } cout << MENU << "\n"; do { char temp[50]; sprintf(temp,"\nCommand #%i> ",command); response = GeneralQuestion(new string(temp)); command++; if (response==NULL) { choice = 'q'; } else { choice = (*response)[0]; if (response) delete response; } switch (choice) { case 'a': case 'A': case 'l': case 'L': response = GeneralQuestion(new string("Enter the number of players (i.e., N): ")); if (!response) { cout << "Invalid capacity. Aborting command.\n"; } else { value = atoi((*response).c_str()); delete response; if (value<1) { cout << "Invalid number of players. Aborting command.\n"; } else { response = GeneralQuestion(new string("Enter the step size (i.e., K): ")); value2 = atoi((*response).c_str()); delete response; if (value2<1) { cout << "Invalid step size. Aborting command.\n"; } else { if (curGame!=NULL) delete curGame; if ((choice=='a') || (choice=='A')) { arrayBased = true; curGame = new ArrayGame(value,value2); cout << "ArrayGame constructor called with N=" << value << ", and K=" << value2 << "\n"; } else { arrayBased = false; curGame = new LinkedGame(value,value2); cout << "LinkedGame constructor called with N=" << value << ", and K=" << value2 << "\n"; } } } } break; case 's': case 'S': if (valid(curGame)) { i = (*curGame).size(); cout << "size( ) returned " << i << "\n"; } break; case 'p': case 'P': if (valid(curGame)) { try { i = (*curGame).playRound(); cout << "playRound( ) returned " << i << "\n"; } catch (GameOverException e) { cout << "playRound( ) threw GameOverException " << e.getMessage() << endl; } } break; case 'c': case 'C': if (valid(curGame)) { try { clock(); clock_t starttime = clock(); i = (*curGame).completeGame(); clock_t endtime = clock(); double_t elapsed = ((double) (endtime - starttime))/CLOCKS_PER_SEC; cout << "Player " << i << " has survived!\n"; #ifdef PRINTTIME cout << "Time used (in seconds) was " << elapsed << "\n"; #endif } catch (GameOverException e) { cout << "playRound( ) threw GameOverException " << e.getMessage() << endl; } } break; case 'v': case 'V': if (valid(curGame)) { bool b = curGame->toggleVerbose(); cout << "toggleVerbose() return " << (b ? "true" : "false") << "\n"; } break; case 'x': case 'X': if (valid(curGame)) { Game *newGame; // test copy constructor if (arrayBased) { newGame = new ArrayGame(*dynamic_cast(curGame)); } else { newGame = new LinkedGame(*dynamic_cast(curGame)); } bool v = curGame->toggleVerbose(); if (v) curGame->toggleVerbose(); // now it should certainly be false curGame->completeGame(); // mess with original game delete curGame; // then delete it // create temp game, invoke assignment operator to reset current game to prev settings if (arrayBased) { curGame = new ArrayGame(2,2); *dynamic_cast(curGame) = *dynamic_cast(newGame); } else { curGame = new LinkedGame(2,2); *dynamic_cast(curGame) = *dynamic_cast(newGame); } v = newGame->toggleVerbose(); if (v) newGame->toggleVerbose(); // now it should certainly be false if (newGame->size()>1) newGame->playRound(); // intentionally mess with new game delete newGame; // delete new game cout << "Based upon use of your copy constructor, assignment operator, and destructor,\n"; cout << "the game in progress has just been replaced by a clone of that game.\n"; cout << "The original game was then intentionally altered and destroyed.\n"; } break; case 'q': case 'Q': quit = true; break; default: cout << "Unrecognized option: " << choice << "\n"; cout << MENU << "\n"; } } while (!quit && (LIMIT<0 || command