Hangman example. Files: hangm.cp (or .cpp depending on your environment) main program CG.h, CG.cp the "Cursor Graphics" header and code files. UT.h UT.Cp some "utility functions" vocab.cp the table of words. You have to create a "project" that incorporates all these files. On Symantec, this should be a C++ with iostreams project. On Borland, you need to create a DOS (or, possibly, an EasyWin) project. This code is the Symantec C++ version. The only change necessary for Borland should be in hangm.cp; the change relates to the initialization of the random number generator. This has to be "randomly initialized" ("seeded") because otherwise the program will always pick words in the same order. This code #includes and uses the Macintosh Toolbox function TickCount() to seed the number generator. If using Borland's environment, you need to substitute a call to one of the clock() functions. ======================= /* hangm.cp */ #include #include #include #include #include #include "CG.h" #include "UT.h" const int kNMOVES = 10; extern UT_Word vocab[]; extern int numwords; UT_Word gGuess; UT_Word gWord; int gLength; int gMatched; void FillSquares(char fill, int num, int x[], int y[]) { for(int i = 0; i < num; i++) { CG_MoveCursor(x[i],y[i]); CG_PutCharacter(fill); } } void ShowFrame(void) { int x[] = { 50, 51, 52, 53, 54, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52 }; int y[] = { 18, 18, 18, 18, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6 }; int n = sizeof(x) / sizeof(int); FillSquares('#', n, x, y); } void ShowBeam(void) { int x[] = { 51, 52, 53, 54, 55, 56, 57, 58 }; int y[] = { 5, 5, 5, 5, 5, 5, 5, 5 }; int n = sizeof(x) / sizeof(int); FillSquares('=', n, x, y); } void ShowSupport(void) { int x[] = { 53, 54, 55 }; int y[] = { 8, 7, 6 }; int n = sizeof(x) / sizeof(int); FillSquares('/', n, x, y); } void ShowRope(void) { int x[] = { 58, 58, 58 }; int y[] = { 6, 7, 8 }; int n = sizeof(x) / sizeof(int); FillSquares('|', n, x, y); } void ShowHead(void) { int x[] = { 59 }; int y[] = { 8 }; int n = sizeof(x) / sizeof(int); FillSquares('@', n, x, y); } void ShowBody(void) { int x[] = { 58, 58, 58, 58 }; int y[] = { 9, 10, 11, 12 }; int n = sizeof(x) / sizeof(int); FillSquares('H', n, x, y); } void ShowLeftArm(void) { int x[] = { 55, 56, 57 }; int y[] = { 10, 9, 9 }; int n = sizeof(x) / sizeof(int); FillSquares('-', n, x, y); } void ShowRightArm(void) { int x[] = { 59, 60, 61 }; int y[] = { 9, 9, 9 }; int n = sizeof(x) / sizeof(int); FillSquares('-', n, x, y); } void ShowLeftLeg(void) { int x[] = { 57, 56, 56 }; int y[] = { 13, 14, 15 }; int n = sizeof(x) / sizeof(int); FillSquares('|', n, x, y); } void ShowRightLeg(void) { int x[] = { 59, 60, 60 }; int y[] = { 13, 14, 15 }; int n = sizeof(x) / sizeof(int); FillSquares('|', n, x, y); } void ShowCartoonPart(int partnum) { switch(partnum) { case 0: ShowFrame(); break; case 1: ShowBeam(); break; case 2: ShowSupport(); break; case 3: ShowRope(); break; case 4: ShowHead(); break; case 5: ShowBody(); break; case 6: ShowLeftArm(); break; case 7: ShowRightArm(); break; case 8: ShowLeftLeg(); break; case 9: ShowRightLeg(); break; } } char GetGuessedChar() { CG_Prompt(" "); CG_Prompt(">"); char ch; do ch = CG_GetChar(); while (!isalpha(ch)); ch = tolower(ch); return ch; } void PickWord(void) { int choice = rand() % numwords; gLength = strlen(vocab[choice]); for(int i = 0; i < gLength; i++) { gWord[i] = vocab[choice][i]; gGuess[i] = '*'; } gWord[gLength] = gGuess[gLength] = '\0'; gMatched = 0; } int CheckChar(char ch) { int count = 0; for(int i = 0; i < gLength; i++) if((gWord[i] == ch) && (gGuess[i] == '*')) { gGuess[i] = ch; count++; } return count; } void Initialize(void) { CG_Initialize(); srand(TickCount()); } int AnotherGame(void) { CG_Prompt("Another Game?"); char ch = CG_GetChar(); CG_Prompt(" "); return ((ch == 'y') || (ch == 'Y')); } void ShowGuess(void) { const xGuess = 6; const yGuess = 4; CG_MoveCursor(xGuess, yGuess); for(int i=0;i 0) { ShowGuess(); gMatched += matched; } else { ShowCartoonPart(count); count++; } gameOverMan = (count >= kNMOVES) || (gMatched == gLength); } if(gMatched==gLength) ShowResult("You won"); else { ShowWord(); ShowResult("You lost"); } return; } int main() { Initialize(); do { PlayGame(); } while( AnotherGame()); CG_Reset(); return 0; } ============= /* The header file for the "utitlity functions", UT.h */ #ifndef __UT__ #define __UT__ const int UT_TXTLENGTH = 60; const int UT_WRDLENGTH = 15; typedef char UT_Word[UT_WRDLENGTH ]; typedef char UT_Text[UT_TXTLENGTH]; int UT_MenuSelect(const UT_Text prompt, const UT_Text options[], int numopts, int listopts); int UT_PickKeyWord(const UT_Text prompt, const UT_Word keywords[], int nkeys); #endif ============ /* The "utilitity functions", UT.cp */ #include #include #include "UT.h" static void ListOptions(const UT_Text options[], int numopts) { cout << "Choose from the following options:" << endl; for(int i = 1; i <= numopts; i++) { cout << setw(4) << i << ": " << options[i-1] << endl; } } static int HandleError(const UT_Text options[], int numopts) { if(cin.eof() || cin.bad()) return 0; cin.clear(); char ch; cin.get(ch); if(ch == '?') ListOptions(options, numopts); else cout << "Illegal input, discarded" << endl; while(ch != '\n') cin.get(ch); return 1; } int UT_MenuSelect(const UT_Text prompt, const UT_Text options[], int numopts, int listopts) { cout << prompt << endl; if(listopts) ListOptions(options, numopts); int choice = -1; do { cout << "Enter option number in range 1 to " << numopts << ", or ? for help" << endl; cin >> choice; if(!cin.good()) { if(!HandleError(options, numopts)) return -1; else continue; } if(! ((choice >= 1) && (choice <= numopts))) { cout << choice << " is not a valid option number, " "type ? to get option list" << endl; } } while (! ((choice >= 1) && (choice <= numopts))); return choice - 1; } ============ /* The header file for "cursor graphics", CG.h */ #ifndef __CGSTUFF__ #define __CGSTUFF__ /* Routines for a "cursor graphics" package. These routines provide a consistent interface, there are differing implementations for Intel (Borland) and PPC (Symantec) platforms. This cursor graphics package is minimalist, it doesn't attempt any optimizations. The windows available for cursor graphics are usually 25 lines by 80 columns. Since output to the last line or last column can sometimes cause undesired scrolling, a smaller work area is defined. */ const int CG_WIDTH = 78; const int CG_HEIGHT = 20; const int CG_PROMPTLINE = 24; /* Initialize --- call before using cursor screen. Reset --- call when finished. */ void CG_Initialize(); void CG_Reset(); /* Movement and output */ void CG_MoveCursor(int x, int y); void CG_PutCharacter(char ch); void CG_PutCharacter(char ch, int x, int y); void CG_ClearWindow(char background = ' '); void CG_FrameWindow(char background = ' '); /* Delay for graphics effects */ void CG_Delay(int seconds); /* Prompting and getting input */ void CG_Prompt(const char prompt[]); void CG_HomeCursor(); char CG_GetChar(); #endif ===== /* The implementation function for cursor graphics. */ /* Remember to set the #define appropriate for your system */ /* #define SYMANTEC or #define DOS etc */ /* Implementation of Cursor Graphics for Symantec 8 and Borland (either DOS-standard or EasyWin) Versions compiled are controlled by compile time #defines SYMANTEC for Mac/PC DOS EASYWIN */ #define SYMANTEC #if defined(SYMANTEC) /* stdio is needed for fputc etc; console is Symantec's set of functions like gotoxy unix for sleep function */ #include #include #include #endif #if defined(DOS) /* conio has Borland's cursor graphics primitives dos needed for sleep function */ #include #include #endif #if defined(EASYWIN) /* Still need conio, but can't use sleep, achieve delay by alternative mechanism */ #include < conio.h> #endif #include "CG.h" void CG_Initialize() { #if defined(SYMANTEC) /* Have to change the "mode" for the 'console' screen. Putting it in C_CBREAK allows characters to be read one by one as they are typed */ csetmode(C_CBREAK, stdin); #else /* No special initializations are needed for Borland environments */ #endif } void CG_Reset() { #if defined(SYMANTEC) csetmode(C_ECHO, stdin); #endif } void CG_MoveCursor(int x, int y) { x = (x < 1) ? 1 : x; x = (x > CG_WIDTH) ? CG_WIDTH : x; y = (y < 1) ? 1 : y; y = (y > CG_HEIGHT) ? CG_HEIGHT : y; #if defined(SYMANTEC) cgotoxy(x,y,stdout); #else gotoxy(x,y); #endif } void CG_PutCharacter(char ch) { #if defined(SYMANTEC) fputc(ch, stdout); fflush(stdout); #elif putch(ch); #endif } void CG_PutCharacter(char ch, int x, int y) { CG_MoveCursor(x,y); CG_PutCharacter(ch); } void CG_ClearWindow(char background) { for(int y=1;y<=CG_HEIGHT;y++) for(int x=1; x<=CG_WIDTH;x++) CG_PutCharacter(background,x,y); } void CG_FrameWindow(char background) { CG_ClearWindow(background); for(int x=2; x