Hangman

Let's make a game Hangman! Toward this goal, we will need to implement some functions.

Part 1: Warmup -- define printSpaced

Our first step is to write a function that prints a string in "hangman format", which for us will just mean spaces between the letters.

Create a program (call it lab07.cpp) with main:

int main() {
  cout << "["; printSpaced("wash"); cout << "]" << endl;
  cout << "["; printSpaced("HelloWorld!"); cout << "]" << endl;
  cout << "["; printSpaced("____e_"); cout << "]" << endl << endl;
  return 0;
}
... which means you'll have to define the printSpaced function.

Hint: the prototype should be

void printSpaced(string);
The output should be exactly:
[w a s h]
[H e l l o W o r l d !]
[_ _ _ _ e _]

Part 2: define mkShadowString

We will also need a function that produces a shadow version of the hangman word. We know the word to guess, but we have to hide it initially from the player.

Append the following code into your main() from Part 1 below what you had above:

string s1 = "food";
string s2 = mkShadowString(s1);
cout << "original: " << s1 << endl;
cout << "  shadow: " << s2 << endl;

string s3 = "require";
string s4 = mkShadowString(s3);
cout << "original: " << s3 << endl;
cout << "  shadow: " << s4 << endl << endl;
... and define a function mkShadowString so that the program produces the output below:
original: food
  shadow: ____
original: require
  shadow: _______
In other words, mkShadowString takes a string as input, and returns a string of the same length, but consisting solely of underscores (_'s).

Note: add this on to the previous part. Keep the functions you already have.

Part 3: define crossOut

We want to keep a running tally of the letters that the player has already guessed. In order to do this, we'll print out all the letters at first like so:

abcdefghijklmnopqrstuvwxyz
But when the user guesses a letter, we want to cross it out:
abcd*fghijklmnopqr*t*vwxyz
The user guessed 'e' 's' and 'u' in the above example.

This part requires you to write a function that creates a new string based on a modification of the given string. I want you to define a function crossOut that works by crossing out a desired letter everywhere it is seen in the string. Add the following code to lab07.cpp's main. Put it below the code from Parts 1-2 in your main():

string t1 = "Go get good food!";
cout << t1 << endl;
t1 = crossOut('o',t1);
cout << t1 << endl;
t1 = crossOut('g',t1);
cout << t1 << endl << endl;
... and define a function crossOut so that the program produces the output below:
Go get good food!
G* get g**d f**d!
G* *et ***d f**d!
You'll want to use this prototype:
string crossOut(char c, string s);

Part 4: define uncover

The last function you'll need is one that takes a masked string (e.g., "______") and uncovers letters that appear in the original string as they are guessed (e.g., "__e_e__"). Add the following code to lab07.cpp's main:

string full = "housepet";
string partial = "________";
cout << partial << endl << endl;

string newPartial = uncover(full,partial,'e');
cout << full << endl;
cout << newPartial << " there " << (partial!=newPartial ? "were " : "were not ") << "e's!"  << endl << endl;
partial = newPartial;                      

newPartial = uncover(full,partial,'q');
cout << full << endl;
cout << newPartial << " there " << (partial!=newPartial ? "were " : "were not ") << "q's!"  << endl << endl;
... and define the function uncover so that the program produces the output below.
________

housepet
____e_e_ there were e's!

housepet
____e_e_ there were not q's!
In other words, this function returns a copy of the second string, BUT all occurrences of the given character within the first string are first copied into the second string at the positions at which they were found. You may assume the string arguments have the same length.

Your main() function should now look like this. If it does not, replace it with our code so it matches the online submit system.

Submit as:

~/bin/submit -c=SI204 -p=Lab07 lab07.cpp

Part 5: Hangman

You'll now use all of the above to make Hangman! Before you start, download words07.txt containing a list of words of 7 characters. If you want, you can use words09.txt too.

Make a copy of your lab07.cpp to hangman.cpp. You probably want to delete everything in your main() function to start fresh, but keep your functions!

Below is an example run of what you need to create:

~/$ ./hangman
Welcome to hangman!
Enter a seed value: 17
Wrong guesses remaining: 8	abcdefghijklmnopqrstuvwxyz
_ _ _ _ _ _ _

: u
Wrong guesses remaining: 8	abcdefghijklmnopqrst*vwxyz
_ _ u _ _ _ _

: t
There were no t's!
Wrong guesses remaining: 7	abcdefghijklmnopqrs**vwxyz
_ _ u _ _ _ _

: s
Wrong guesses remaining: 7	abcdefghijklmnopqr***vwxyz
s _ u _ _ _ s

: e
Wrong guesses remaining: 7	abcd*fghijklmnopqr***vwxyz
s _ u _ _ e s

: r
Wrong guesses remaining: 7	abcd*fghijklmnopq****vwxyz
s _ u r _ e s

: f
There were no f's!
Wrong guesses remaining: 6	abcd**ghijklmnopq****vwxyz
s _ u r _ e s

: p
There were no p's!
Wrong guesses remaining: 5	abcd**ghijklmno*q****vwxyz
s _ u r _ e s

: o
Wrong guesses remaining: 5	abcd**ghijklmn**q****vwxyz
s o u r _ e s

: c
You win!!!! Word was sources

If the number of guesses hits zero, then instead print "You lose!!!!". It thus ends with two possible outputs:

You win!!!! Word was THEWORD
You lose!!!! Word was THEWORD

Your program must first choose a random word from the file "words07.txt" at the start of the program. You can hardcode this file name into your program. How do you pick a random number? Recall that you first need a seed value that you will get from the user, and then get a random number like so:

int seed;
cin >> seed;
srand(seed);
int n = rand() % 909;

We'll assume all files like "words07.txt" have at least 909 words in them, so we generate a random number up to that. You must then read the nth word from that file where n is your random number! Start counting the words in the file at 0, as usual. You'll also need to include cstdlib for these rand functions.

Other details that you must follow:

Submit as:

~/bin/submit -c=SI204 -p=Lab07 lab07.cpp hangman.cpp

Part 6: (Going Further) Extra challenge

The only thing we haven't done is to draw the little man. Rather than having a countdown with the number of guesses remaining, draw the man! To get you started, here are strings that will help you:

// use the code to draw the hanging man:

    string fh = "  ____ \n"
                "  |   |\n"
                " _O_  |\n"
                "  |   |\n"
                " / \\  |\n"
                "______|_\n";

    string ch = "  ____ \n"
                "  |   |\n"
                "      |\n"
                "      |\n"
                "      |\n"
                "______|_\n";

    cout << fh << endl;
    cout << ch << endl;
Note: If you get a nice working game, please demo it to your instructor.