I'm pretty convinced that the code in the book for the MagicMind game doesn't work correctly. It compiles all right, but the checkGuess method in MindPlayer.m is faulty. Consider, for example, a rack of Red, Green, Black and Yellow, which is
rgky. If the player guesses Black, Green, Black, Yellow, which is
kgky, then the checkGuess method returns correctColorAndPosition: 2 and correctColorOnly: 1, which is wrong. The correct answer is correctColorAndPosition: 3, correctColorOnly: 0. The problem is the first 'k' in the guess is matched up via color only with the 'k' in the rack, which is immediately set to 'x', so by the time the loop gets to the second 'k' in the guess, there is no 'k' in the rack anymore.
The code should be amended to first loop through all pegs to check for correct color and position, and then afterwards double-loop through separately to check for correct color only. The book code tries to do this all in one outer loop. Code for the correct implementation of correctGuess is below:
Code:
// Check the guess against the rack
-(NSString*) checkGuess:(NSString*) guess
{
// Declare two ints to keep track of response criteria
int correctColorAndPosition = 0;
int correctColorOnly = 0;
// Declare a string to temporarily hold the guess peg letter
char tempGuessPeg;
// Build a temporary rack
char tempRack[4];
for (int i=0; i<=3; i++)
{
tempRack[i] = rack[i].color;
}
// Loop through each guess peg to check for color and position match
for (int i=0; i<=3; i++)
{
tempGuessPeg = [guess characterAtIndex:i];
// If pegs are identical, increment correctColorAndPosition
if (tempGuessPeg == tempRack[i])
{
correctColorAndPosition++;
// Change the temp rack color to 'x' to indicate
// that it has already been matched to a guess peg
tempRack[i] = 'x';
}
}
// Loop through each guess peg to check for color only match
for (int i=0; i<=3; i++)
{
tempGuessPeg = [guess characterAtIndex:i];
for (int j=0; j<=3; j++)
{
// Is there a peg this color in the rack?
if (tempGuessPeg == tempRack[j])
{
correctColorOnly++;
// Change the temp rack color to 'x' to indicate
// that the color has been matched to a guess peg
tempRack[j] = 'x';
break;
}
}
}
// Determine if the user won
if (correctColorAndPosition == 4)
{
return @"win";
}
else
{
return [NSString stringWithFormat:
@"\nCorrect Color And Position: %i \nCorrect Color Only: %i",
correctColorAndPosition, correctColorOnly];
}
}