You are to write a program to play the game "Mastermind". In this game, the computer selects a sequence of characters, and the user attempts to guess the sequence. The number of characters in the sequence (dimension) will be chosen by the player. The range of characters is from 'A' up to some maximum character, chosen by the player. The range of dimensions that the player can choose is from 3 to 6. For instance, if the player chooses a maximum character of 'F' and a dimension of 4, then the computer might select a pattern like AFFB.

The computer responds to each player guess by telling the player the number of exact and inexact matches in his/her guess, as defined below. When the player guesses the pattern correctly, the computer asks if the player would like another game. After each game in the session, the computer reports the average number of guesses the player has taken to find patterns so far. The player has a certain number of chances to guess the pattern before they lose the game. The number of guesses that the player can try is the ceiling of (dimension of the game x the number of possible letters / 3). In the example with a maximum character of 'F' and a dimension of 4, the allowable guesses would be ceil(4*6/3) = 8. If the player does not guess the pattern by the number of allowed guesses, they lose the game. See the test outputs for the messages to display to the player.

  • Max character: 'A' - 'F'
  • Dimensions: 3-6
  • Number of Guesses: ceiling of (dimension of the game) x (the number of possible letters) / 3

Note: To use the ceil function you must inlcude math.h and compile with a -lm flag.

Matching Rules

To define exact and inexact matches, let's assume that the computer's pattern is AFFB and the player has guessed BFAB.

The F and the second B in the user's guess are exact matches, because they match the corresponding characters in the computer's pattern. The A in the player's guess is an inexact match because there is an A in the computer's pattern, but it is in a different place than the A in the player's pattern.

A given letter may be used for only one match -- an exact match if possible, or an inexact match if there is no exact one. For instance, the first B in the player's pattern does not form an inexact match with the B in the computer's pattern because the computer's B has already been "used up" by the exact match mentioned earlier. Likewise, the second F in the computer's pattern does not form an inexact match with the player's F because the user's F was "used up" in an exact match.

Initial Input

To start the game, the player enters the maximum letter, the number of letters in the pattern (dimension), and a random "seed" value.

The largest maximum letter allowed is 'F'. Print an error message as shown in the sample run below if any of these rules is violated.

Sample Run

Note 1: This is a sample run - many other results are possible with many different inputs - be sure to read the specifications carefully for details.

Note 2: All player input is bold in the sample run for clarity only - your program is not expected to behave this way.

Note 3: The output to the right of the ":" (if not user-input which is bold) is a combination of calculated values and hard-coded text.

Sample Run

Enter max letter: H
Max letter must be between A and F.
Enter max letter: F
Enter game dimension: 2
Dimension must be between 3 and 6.
Enter game dimension: 9
Dimension must be between 3 and 6.
Enter game dimension: 4
Enter the seed: 1
Starting game...
You have 8 guesses left!
Enter Guess (4 chars): ABCD
XXXX
----
(0,2) ABCD
You have 7 guesses left!
Enter Guess (4 chars): EFGC
One or more chars out of range A-F, try again: EFDC
XXXX
----
(0,2) ABCD
(1,1) EFDC
You have 6 guesses left!
Enter Guess (4 chars): BEDE
XXXX
----
(0,2) ABCD
(1,1) EFDC
(3,0) BEDE
You have 5 guesses left!
Enter Guess (4 chars): BEDB
XXXX
----
(0,2) ABCD
(1,1) EFDC
(3,0) BEDE
(4,0) BEDB
You win!!
Pattern found in 4 attempts! Current average: 4.000
Another game [Y/N]? y
Starting game...
You have 8 guesses left!
Enter Guess (4 chars): ABCD
XXXX
----
(1,1) ABCD
You have 7 guesses left!
Enter Guess (4 chars): FFEE
XXXX
----
(1,1) ABCD
(2,0) FFEE
You have 6 guesses left!
Enter Guess (4 chars): ABFE
XXXX
----
(1,1) ABCD
(2,0) FFEE
(1,3) ABFE
You have 5 guesses left!
Enter Guess (4 chars): FEBA
XXXX
----
(1,1) ABCD
(2,0) FFEE
(1,3) ABFE
(2,2) FEBA
You have 4 guesses left!
Enter Guess (4 chars): FBEA
XXXX
----
(1,1) ABCD
(2,0) FFEE
(1,3) ABFE
(2,2) FEBA
(4,0) FBEA
You win!!
Pattern found in 5 attempts! Current average: 4.500
Another game [Y/N]? n

Code - What do I do?

You are given a file (mastermind.c) to start with that contains all the functions you have to implement. Comments clearly mark where you need to "do something". The functions are currently empty and you need to add code to implement them. Look carefully at the structure defined for you to use with your implementation. The code should compile “as is”. Then begin work on implementing the following functions:

/*
* Use the rand() function to return a random character
* in-between 'A' and the maxChar.
*/
char getRandChar(char maxChar)
/*
* Prompt the user for characters to fill in the letters array.
* Make sure all input characters are between 'A' and maxChar.
* "dim" indicates how many letters to get.
*
* HINT: Do a "dummy" scanf before you start scanning chars,
* like we discussed in class.
*
* HINT 2: Do NOT use string functions. Process one character at
* time up to the dim. There is no room for a null char in the
* letters array.
*/
void getGuess(char letters[], int dim, char maxChar)
/*
* Display the mastermind board according to the following example:
*
* XXXX
* ----
* (0,2) ABCD
* (0,3) ABBD
* (3,0) BEDE
*
* "tries" indicates how many guesses are in the Guess array.
* "dim" indicates how many letters are in each Guess.
*
* HINT: Remember... the letters must be printed one at a time.
* They do not end in the null char.
*/
void printBoard(Guess guesses[], int tries, int dim)

After implementing and testing the above functions, write the main function such that it implements the mastermind game. I have written a function for you that determines the number of exact and inexact matches for a guess. You pass the array of Guesses and the index of the Guess you want analysed to the function. It fills in the exact and inexact matches for that Guess. It also returns (via the return value) whether the guess matches the answer. It returns 1 for "true" (a win) or 0 for "false" (not a complete match yet). The prototype for this function is shown below:

int calcMatches(char answer[], int dim, Guess guess[], int index);

To use the function, download the file util.o from my account. See the “Given Files” section above.

Call the function from your code just like you would if you had written the function yourself. Then, when you compile your code, use the following command:

gcc mastermind.c util.o

Specification

  • Your program must compile without error or warning using the gcc compiler and the -Wall -ansi - pedantic compiler flags.
  • Your program prompts must match the specified prompts exactly (spelling, capitalization, et cetera).
  • Your program outputs must match the specified outputs exactly (spelling, capitalization, et cetera) when run on unix1-4.
  • The average guess output should be shown to three decimal places.
  • When the player enters their guess, you may assume that they will only enter capital letters. They will not enter lowercase letters, numbers, too few letters, or too many letters. The only error checking you need to do is to make sure the capital letters they type are in the valid range, from 'A' to the max letter.
  • Your program will be tested with input you have not seen and must work correctly for any valid input.
  • Implement your solution in a file called mastermind.c.
  • Use the #defines already given in the code.
  • Use srand and rand to get random numbers.

Hints/Suggestions

  • There is a sample executable available to for you to use, see below. Play with it until you are sure you understand its workings. Your program must match the behavior of mine exactly when run on unix1. (Your program may choose different random patterns on your home machine even if started with the same random number "seed".)
  • Read the program specifications fully before beginning to write code. Ask your instructor for any necessary clarifications as early as possible.
  • Think carefully about your random letter generating code. It's very easy to misdesign the random pattern generator so that you never get the maximum character (if your maxchar is 'F', you only get 'A' - 'E'). Test for this case.
  • To match my random patterns, use the standard number generator for the C programming language (srand and rand). Use the modulo operator to reduce the large random integer the generator gives you, down to an integer just large enough for your needs. (e.g. a value of 0-5 to choose one of 6 different letters). Use the seed value just once in the program as the argument to srand.
Academic Honesty!
It is not our intention to break the school's academic policy. Posted solutions are meant to be used as a reference and should not be submitted as is. We are not held liable for any misuse of the solutions. Please see the frequently asked questions page for further questions and inquiries.
Kindly complete the form. Please provide a valid email address and we will get back to you within 24 hours. Payment is through PayPal, Buy me a Coffee or Cryptocurrency. We are a nonprofit organization however we need funds to keep this organization operating and to be able to complete our research and development projects.