CS102 Lecture Notes -- the "Master Mind" game

James S. Plank

Before going on, here are the pictures of various incantations of the board game.


Program 1 -- An easy number-guessing program

In numguess.cpp, we have a simple number-guessing program that features if statements, a while loop, and some compound boolean expressions.

Copy it, compile and run it to see how it works.


Program 2 -- Easy Master Mind

In easymm.cpp, we have a simple "Master-Mind" program, where the user guesses a number, and if not correct, we report the number of correct digits, and the number of correct digits that are in the proper position.

The program assumes that the answer and the guesses all have different digits -- otherwise, the answers might not make sense. Again, copy it, compile and run it.


Program 3 -- Master Mind Turned into an Object-Oriented Program

In mmoo.cpp, we have turned this into an object-oriented program. Now, we have a class called MasterMind, which has two pieces of data -- the answer and the number of guesses, and three methods -- play_game() which plays a game, is_legal_answer(), which tests whether an answer is a legal one (between 0 and 999 and having no repeated digits), and get_legal_guess(), which prompts the user for a guess, tests for legality, and only returns when the user has entered a legal guess.

This features (obviously), classes, methods, a method with a parameter (is_legal_answer()), methods that return integers (is_legal_answer() and get_legal_guess()), plus a nice use of a do/while loop to get the initial answer.

Again, copy, compile and run -- if various parts of the program confuse you, insert some cout statements to help you figure out what's going on.


Program 4 -- Better design; Splitting into multiple files

Ok, now we split the program into three files. First is the interface file mm.h, which defines, but does not implement the class. This should be included by any program file that uses or implements the class. Since it uses the string class, we should put the include and using namespace std lines in there.

Ok, now look at the class definition:

class MasterMind {
  public:
    int is_legal_answer(int n);
    int get_legal_guess();
    void play_game(string player1, string player2);
    int get_nguesses();
  private:
    int answer;
    int nguesses;
    string p1;
    string p2;
};

We have added a few things. First, we have allowed whoever is calling play_game() to specify player names. These are strings and use the string class from the standard C++ library. You can get more information about the string class from a web site like http://www.cprogramming.com/tutorial/string.html (The only downside of this one is that it fires up a pop-up window when you first click it). For this program, the only reason that we use strings is to be able to hold text, like a player's name.

We've also added a method called get_nguesses(). We do this if we want to find out how many guesses the person took who played the last game. It would be nice if we could read the nguesses variable, but since it is private we can only read it when we are implementing the class's emthods. To have it visible to another procedure or program, we instead have them call get_nguesses().

We implement the methods of MasterMind mm.cpp. Note that we've modified the methods so that they use the player names instead of "Player 1", and "Player 2".

Finally, we have two programs that use the MasterMind class to play a game. The first is one_game.cpp, which has "Tom" and "Jerry" play a game.

int main()
{
  MasterMind game;

  game.play_game("Tom", "Jerry");

  return 0;
}

Copy the three files to your directory (mm.h, mm.cpp, and one_game.cpp), and compile them with

UNIX> g++ mm.cpp one_game.cpp

When you run the a.out file, you'll get to play the game as Tom & Jerry.

Finally, the file two_games.cpp has a program that plays two games between our MasterMind Game-Box protagonists, "Folded-hands-guy" and "His-Honey." When the two games are over, it declares a winner. Note how get_nguesses() is used to get the number of guesses after the game is played.

int main()
{
  MasterMind game;
  int p1score, p2score;

  game.play_game("Folded-hands-guy", "His-Honey");
  p1score = game.get_nguesses();

  game.play_game("His-Honey", "Folded-hands-guy");
  p2score = game.get_nguesses();

  if (p1score < p2score) {
    cout << "Player 1 wins.\n";
  } else if (p1score > p2score) {
    cout << "Player 2 wins.\n";
  } else {
    cout << "It's a tie.\n";
  }
  return 0;
}

Copy two_games.cpp over to your directory, and compile it with

UNIX> g++ mm.cpp two_games.cpp

Try it out. One of the lessons to come away with here is that by defining the class and putting it into an interface and implementation file, we can use it in two different programs (one_game and two_games).

If you want some practice, see if you can write a new program called mano-a-mano, which has "Folded-hands-guy" and "His-Honey" square off again, but whenever they tie, they play another pair of games to break the tie.