Friday, July 22, 2011

Java Console Programming - Master Mind

Related article


The Game Of Master Mind


I found the following "functional spec" in programmingforums.org.

We will implement this game with a top down design approach.



Mastermind Game

You are to write a program that generates a secret code at random and let the human player guess this code. Each time the player inputs his guess, the program responds with a score that reflects how close or far the player's guess is from the secret code.

To make the game interesting, this secret code is made up of animals. There are 12 animals to choose from, namely: Ant, Bear, Cat, Dog, Emu, Goat, Lizard, Monkey, Parrot, Rabbit, Snake, and Tiger.

Upon start, the program chooses a code, which is 4 randomly selected animals. The program cannot select the same animal more than once in the code. So the 4 animals are all different from each other.

Examples of valid codes:
[ Tiger, Snake, Monkey, Rabbit ]
[ Monkey, Parrot, Snake, Ant ]

Examples of invalid codes:
Reason
[ Ant, Cat, Monkey, Ant ] Ant selected twice
[ Rabbit, Monkey, Snake ] Code must be 4 animals

Scoring:
The objective of the game is for the player to guess the 4 animals, with the least number of attempts. The program has two levels of difficulty. In the low difficulty setting, the player has to guess the 4 animals but not necessarily in the same order.

For example, if the secret code is [Cat, Dog, Ant, Tiger] and the player
guesses [Dog, Tiger, Ant, Cat], the guess will be considered correct.

In the low difficulty setting, the program takes the input guess and finds out which animals in the input matches with those on the code. The score is the number of correct animals. Obviously, if the score is 4, the player wins and the program ends. Here are some examples:

Secret Code: [ Cat, Dog, Ant, Tiger ]
Guess: [ Ant, Rabbit, Monkey, Snake ] Score is 1 (Ant matches)
Guess: [ Rabbit, Ant, Dog, Snake ] Score is 2 (Ant and Dog)
Guess: [ Dog, Tiger, Ant, Cat ] Score is 4 (Player wins)

In the high difficulty setting, the player has to guess the 4 animals and also the positions of each animal. In the third guess above, notice that only "Ant" is guessed correctly at the right position (i.e., third position). In this level, the program outputs two numbers for the score: (a) number of correct animals; and (b) number of
correct animals in the correct position. Study the examples below. Note the computer-generated scores for (a) and (b) are shown on the right side.

Secret Code: [ Cat, Dog, Ant, Tiger ]
Computer Outputs Score
Guess: [ Rabbit, Ant, Dog, Snake ] (a) is 2 (b) is 0
Guess: [ Cat, Ant, Dog, Snake ] (a) is 3 (b) is 1
Guess: [ Cat, Dog, Ant, Snake ] (a) is 3 (b) is 3
Guess: [ Cat, Dog, Ant, Tiger ] (a) is 4 (b) is 4

Obviously, the required score to win is 4 for both (a) and (b). Only then does the program terminate.

Below is a list of specific requirements that your program must satisfy.
1. Your program should use the time() function to seed the random number generator. This will make the program select different codes each time it is executed. Study how to use this with srandom() function.
2. The required input format for each guess is 4 characters. Notice that the 12 animals have different starting characters. Use the first character of each animal as a means to identify it. For example, an input
of "CDAT" means [Cat, Dog, Ant, Tiger]. This makes it unnecessary to use "Ant", "Tiger", etc. for input.
3. Your program must also validate the input. Here are some examples of invalid inputs:
Input Reason Error Message
CDAA A is repeated "Repeated Animal"
SADQ Q is not a valid animal "Invalid Animal"
Use the error messages above when an invalid user input is encountered.


Design

This is a good example of console programming that implements something interesting.

We will use System.in for reading input, System.out for printing output.

There is a java.io.Console class which is available after JDK 1.5, but we won't use this class anyway.

Top down Approach


We will implement the game using the top-down approach. First of all, let's define the flow in the main() method.



Now we are going to fill the above methods one by one. A good starting point is to define the game flow first. Hence the first method I choose to fill is game(). Since the function names used below are self-documentary, the game flow should be easy to understand.






Quick Prototyping

Now we are going to create a first version that doesn't have compilation error. We will create empty functions if necessary.





Now we have a completed prototype, compile it, and run it. It doesn't do anything meaningful right now. But it is a good starting point. Once all the empty functions are filled, we have a fully working game.

Shuffle()


There are quite a few empty methods to be implemented. What should be next ?. There are many reasonable choices. I would choose shuffle() to generate a secret code. Before writing the method, we need to define data structure to hold the animal names and the animal codes(the first letter).






Once we have the data structure ready, we can generate the secretCode, which stands for the 4 randomly picked animals. We are going to use the Knuth Shuffling algorithm to randomize the permutation array. Then use the first 4 index in the permutation to pick 4 animals.





displaySolution()

Now we want to check our shuffe() method, therefore the next reasonable method to implement is displaySolution()



Now it is time to recompile and run MasterMind.java. It will display 4 randomly picked animals every time you run the program.


getPlayeGuess() - getting input from user

Up to now the program is not interactive. We are going to enable the input function right now.



The above method call two auxiliary methods,getInputLine() and validateInput().

getInputLine() - reading from System.in

It simply reads a line from System.in. Implementation follows :





validateInput()

When the user enter a guess, we must validate it.




The above method introduces another auxiliary method, getAnimalIndex(), which would return -1 if the character is not a valid animal, otherwise it would return a index to the array of animals. This function is very simple, it is just a single line method.



Now you may compile and run the program again. You may test the program with the following input. The blue part is input by player. The program will quit whenever a valid input is read.


Animal Code : ABCDEGLMPRST
Enter your guess : abcde
Must enter 4 letters
Animal Code : ABCDEGLMPRST
Enter your guess : abcx
Invalid Animal
Animal Code : ABCDEGLMPRST
Enter your guess : abcc
Repeated Animal.
Animal Code : ABCDEGLMPRST
Enter your guess : abcd
Congratulations ! The solution is :
[Snake, Bear, Ant, Emu]


setDifficulty()

At this point, we have the input validation method ready. The next reasonable step is to calculate and display the score for each guess. However, since the game provides two difficulty settings, which would affect the score calculation method, we must first implement the setDifficulty() method.



calculateScore()

We may now implement calculateScore().




And of course we must display the calculated score, hence the next method would be displayScore()

displayScore()





At this point we have already completed the whole game flow. You may compile and play the game now. We are still missing the replay() method, which asks the player to play another game or not after a successful guess. But it doesn't affect the whole game flow. The method replay() will be implemented in the full source anyway.

Full Source




Conclusion

This article demonstrated how to convert a functional specification into a running program, using a top down design approach. To see example of bottom-up design, read this article :Tetris from Scratch

No comments:

Post a Comment