C++ Guessing Game structing

profilef.a.qx8t
lab01files.zip

Lab01Files/build.bat

@echo off cls set DRIVE_LETTER=%1: set PATH=%DRIVE_LETTER%\MinGW\bin;%DRIVE_LETTER%\MinGW\msys\1.0\bin;c:\Windows;c:\Windows\system32 g++ -c Keyboard.cpp g++ -c Random.cpp g++ -c String.cpp g++ -c ReadFile.cpp g++ -c WriteFile.cpp g++ -c PlayerGuessDriver.cpp g++ -o PlayerGuess.exe PlayerGuessDriver.o ReadFile.o WriteFile.o String.o Keyboard.o Random.o

Lab01Files/Keyboard.cpp

#include "Keyboard.h" #include <iostream> int readInt(string prompt) { cout << prompt; int val = 0; cin >> val; return val; } int getValidatedInt(string prompt, int min, int max) { int validated = readInt(prompt); cout << validated << endl; while(validated < min || validated > max) { validated = readInt(prompt); cout << validated << endl; } return validated; } double readDouble(string prompt) { cout << prompt; double val = 0; cin >> val; return val; } double getValidatedDouble(string prompt, double min, double max) { double validated = readDouble(prompt); cout << validated << endl; while(validated < min || validated > max) { validated = readDouble(prompt); cout << validated << endl; } return validated; } String* readString(string prompt) { cout << prompt; string text; getline(cin, text); String* str = createString(text.c_str()); return str; }

Lab01Files/Keyboard.h

#if !defined KEYBOARD #define KEYBOARD #include "Text.h" #include <string> using namespace std; //pre: the string (character literal) that will prompt the user for input //post: the input read from the keyboard interpreted as an int is returned int readInt(string prompt); int getValidatedInt(string prompt, int min, int max); //pre: the string that will prompt the user for input //post: the input read from the keyboard interpreted as a double is returned double readDouble(string prompt); double getValidatedDouble(string prompt, double min, double max); //pre: the string that will prompt the user for input // the string to store the user input and the length of the input storage string //post: the text read from the keyboard is copied into the storage string String* readString(string prompt); #endif

Lab01Files/Laboratory 01_ Guessing Game.pdf

8/28/2014 Laboratory 01: Guessing Game

http://mboshart.dyndns.org/boshart/2111Labs/Lab01.html 1/3

Laboratory 01: Guessing Game Download the following files and place them in your working directory:

Starting code for this lab:

Lab01Files.zip //provided, completed files, refer to header files for method signatures PlayerGuessDriver.cpp //most of the work is in this file range.txt //contains the two integers that define the range for the secret number build.bat //convenience file for compiling and linking

Guessing Game

In this lab, you will write a simple guessing game. The computer will generate a random integer within a valid specified range, inclusive (min, max) read in from a text file. The user then tries to guess the generated secret number. If the guess is not correct, the user is told whether they are too high or too low. When the secret number has been correctly guessed, the total number of guesses required is reported. The user is then asked if they want to play again.

You will need to use my String, ReadFile, Keyboard, and Random structs to complete this lab. To use these structs, you can refer to the method signatures in the header files for each struct.

#include "Text.h" #include "ReadFile.h" #include "Random.h" #include "Keyboard.h"

Complete the following methods:

int getSecret(int* range) //obtain a randomly generated secret number in the range (started for you) int* getRange() //get the name of the text file and read the range from the text file (range is an int array of size 2, dynamically allocated using new, delete pointers when finished with them) int getGuess(int* range) //obtain a guess (ask again if the guess is not in the range) GuessEnum processGuess(int guess, int secret) //determine whether a guess is correct (return EXACT), too low (return TOO_LOW), or too high (return TOO_HIGH) int play(int* range, int secret) //loops until the secret number has been guessed and returns the total number of guesses required (calls getGuess and processGuess) int main() //starts up a game and loops as long as the user wants to keep playing (calls getRange, getSecret, and play, deletes the dynamically allocated

8/28/2014 Laboratory 01: Guessing Game

http://mboshart.dyndns.org/boshart/2111Labs/Lab01.html 2/3

integer array)

I like to use many short methods when I write programs. This allows you to increase the level of abstraction in your program, a term which you will hear very frequently this semester. Sections of code are replaced by well-named method calls. This improves the readability of your program.

Batch File

Typing at the command line every time that you want to compile and run can be tedious. Instead, you can type your command line instructions into a text (batch) file with the .bat extension. Then you can simply type the name of the batch file at the command prompt followed by the drive letter of your jump drive (i.e. build e) and all of your instructions listed in the batch file will automatically execute in order. Take a look at build.bat to see the set of command line operations that you can use to compile and link your work for this lab. If you don't need to compile certain files, you can comment out the corresponding line with ::. This makes it easy to select and deselect which files to compile.

Artificial Intelligence

Write a new driver file (ComputerGuessDriver.cpp) so that the user picks the secret number and the computer tries to guess the number. Try to have the computer use as few guesses as possible. What is a secret number that forces the computer to take the maximum number of guesses? You will need to modify build.bat.

8/28/2014 Laboratory 01: Guessing Game

http://mboshart.dyndns.org/boshart/2111Labs/Lab01.html 3/3

Lab01Files/PlayerGuessDriver.cpp

Lab01Files/PlayerGuessDriver.cpp

#if   ! defined  ( GUESS_ENUM )
#define  GUESS_ENUM
    enum   GuessEnum   { EXACT ,  TOO_LOW ,  TOO_HIGH };
#endif

#include   "Text.h"
#include   "ReadFile.h"
#include   "Random.h"
#include   "Keyboard.h"

#include   < iostream >
using   namespace  std ;

//insert your methods here












int  main ()
{
    String *  n  =  createString ( "n" );
    String *  ready_str  =  readString ( "Are you ready to play? (y/n) " );

    while   ( compare ( n ,  ready_str )   !=   0 )
    {
      destroyString ( ready_str );
   
       //DO THIS














      cout  <<   "You got it in "   <<  total_guess  <<   " guesses!"   <<  endl ;
      cin . ignore ();
      ready_str  =  readString ( "Are you ready to play? (y/n) " );
    }

   destroyString ( ready_str );
   destroyString ( n );
    return   0 ;
}

Lab01Files/Random.cpp

#include "Random.h" #include <time.h> #include <stdlib.h> void randomInit() { srand (time(NULL)); } int getRandomInt(int lower, int upper) { int diff = upper - lower + 1; int random_num = rand()%diff; random_num = random_num + lower; //gives a number between lower and upper, inclusive return random_num; } float getRandomFloat(float lower, float upper) { float r_float_1 = (float) rand(); float r_float_2 = (float) RAND_MAX; float random_normalized = r_float_1/r_float_2; //between 0.0 and 1.0 float random_float = lower + random_normalized*(upper - lower); return random_float; }

Lab01Files/Random.h

#if !defined RANDOM_H #define RANDOM_H void randomInit(); int getRandomInt(int lower, int upper); float getRandomFloat(float lower, float upper); #endif

Lab01Files/range.txt

1 1000

Lab01Files/ReadFile.cpp

#include "ReadFile.h" #include <iostream> #include <string> ReadFile* createReadFile(const char* file_name) { ReadFile* rf = new ReadFile; rf->input_file.open(file_name); rf->closed = false; rf->_eof = false; return rf; } void destroyReadFile(ReadFile* rf) { close(rf); delete rf; } bool eof(ReadFile* rf) { return rf->_eof; } void close(ReadFile* rf) { if (!rf->closed) { rf->input_file.close(); rf->closed = true; } } String* readLine(ReadFile* rf) { if (rf->closed) return NULL; if (rf->_eof) return NULL; string text; rf->_eof = !(getline(rf->input_file, text)); String* str = createString(text.c_str()); return str; }

Lab01Files/ReadFile.h

#if !defined READ_FILE #define READ_FILE #include "Text.h" #include <fstream> using namespace std; struct ReadFile { ifstream input_file; bool _eof; bool closed; }; ReadFile* createReadFile(const char* file_name); void destroyReadFile(ReadFile* rf); String* readLine(ReadFile* rf); bool eof(ReadFile* rf); void close(ReadFile* rf); #endif

Lab01Files/String.cpp

#include "Text.h" #include <stdlib.h> //needed for atoi and atof #include <cstring> //needed for strlen and strcmp #include <sstream> #include <iostream> using namespace std; String* createString(const char* char_array) { int sz = strlen(char_array); char* text = new char[sz+1]; for (int i = 0; i < sz; i++) { text[i] = char_array[i]; } text[sz] = 0; //null terminator String* str = new String; str->text = text; str->sz = sz; return str; } int length(String* str) { return str->sz; } const char* getText(String* str) { return str->text; } int compare(String* str1, String* str2) { return strcmp(str1->text, str2->text); } void displayString(String* str) { const char* text = str->text; cout << text; } void destroyString(String* str) { const char* text = str->text; delete[] text; delete str; } int find(String* str, char delimiter, int start) { int sz = str->sz; const char* text = str->text; if (start >= sz || start < 0) return -1; int loc = sz; for (int i = start; i < sz; i++) { if (text[i] == delimiter) { loc = i; break; } } return loc; } //the substring will use the characters from start to end inclusive String* substr(String* str, int start, int end) { if (start > end || start < 0) return NULL; int sz = str->sz; if (start > sz || end > sz) return NULL; String* sub = new String; const char* text = str->text; int sub_len = end - start + 1; char* sub_text = new char[sub_len + 1]; int count = 0; for (int i = start; i <= end; i++) { sub_text[count] = text[i]; count++; } sub_text[count] = 0; sub->text = sub_text; sub->sz = sub_len; return sub; } int a_to_i(String* str) { const char* text = str->text; return atoi(text); } float a_to_f(String* str) { const char* text = str->text; return atof(text); } String* i_to_a(int number) { stringstream out; out << number; const char* text = out.str().c_str(); return createString(text); } String* f_to_a(float number) { stringstream out; out << number; const char* text = out.str().c_str(); return createString(text); }

Lab01Files/Text.h

#if !defined STRING_STRUCT #define STRING_STRUCT struct String { const char* text; int sz; //length of string not including null terminator }; String* createString(const char* char_array); void displayString(String* str); void destroyString(String* str); int length(String* str); const char* getText(String* str); int a_to_i(String* str); float a_to_f(String* str); String* i_to_a(int number); String* f_to_a(float number); //find the location of a particular character in a String and return the index if found //preconditions: // str is the String being examined for the character delimiter (str must point to a valid String) // delimiter is the character being searched for // start is the index to start the search at (the first index of the String is 0, start cannot exceed the length of the String) //postconditions: // if the preconditions are met, the index of the first delimiter encountered at or after the start index is returned // if the delimiter is not present in the String at index start or later, -1 is returned // if the preconditions are not met, no guarantees on output are made int find(String* str, char delimiter, int start); //creates a new String that is extracted from an existing String with characters specified by the start and end indices //preconditions: // str is the String from which the substring will be extracted (str must point to a valid String) // start and end are the indices used to create the substring // start must be less than or equal to end, start must be >= 0, end must be >= 0, end < the length of the String //postconditions: // if the preconditions are met, the String extracted from the parameter String // that starts at index start and ends at index end is created and returned // the original string is unaffected String* substr(String* str, int start, int end); //need to document that this compare only has three possible return values (-1, 0, 1) int compare(String* str1, String* str2); #endif

Lab01Files/WriteFile.cpp

#include "WriteFile.h" #include <sstream> WriteFile* createWriteFile(const char* file_name) { WriteFile* wf = new WriteFile; wf->output_file.open(file_name); wf->closed = false; return wf; } void destroyWriteFile(WriteFile* wf) { close(wf); delete wf; } void close(WriteFile* wf) { if (!wf->closed) { wf->output_file.close(); wf->closed = true; } } void writeLine(WriteFile* wf, String* line) { if (!wf->closed && length(line) > 0) { wf->output_file << getText(line) << endl; } }

Lab01Files/WriteFile.h

#if !defined WRITE_FILE #define WRITE_FILE #include "Text.h" #include <fstream> using namespace std; struct WriteFile { ofstream output_file; bool closed; }; WriteFile* createWriteFile(const char* file_name); void destroyWriteFile(WriteFile* wf); void writeLine(WriteFile* wf, String* line); void close(WriteFile* wf); #endif