Bulls and Cows


Task

Create a four digit random number from the digits   1   to   9,   without duplication.

The program should:

   ask for guesses to this number
   reject guesses that are malformed
   print the score for the guess


The score is computed as:

 The player wins if the guess is the same as the randomly chosen number, and the program ends.
 A score of one bull is accumulated for each digit in the guess that equals the corresponding digit in the randomly chosen initial number.
 A score of one cow is accumulated for each digit in the guess that also appears in the randomly chosen number, but in the wrong position.


Related tasks

   Bulls and cows/Player
   Guess the number
   Guess the number/With Feedback
   Mastermind


import system'routines;
import extensions;
 
class GameMaster
{
    object theNumbers;
    object theAttempt;
 
    constructor()
    {
        // generate secret number
        var randomNumbers := new int[]{1,2,3,4,5,6,7,8,9}.randomize(9);
 
        theNumbers := randomNumbers.Subarray(0, 4);
        theAttempt := new Integer(1);
    }
 
    ask()
    {
        var row := console.print("Your Guess #",theAttempt," ?").readLine();
 
        ^ row.toArray()
    }
 
    proceed(guess)
    {
        int cows := 0;
        int bulls := 0;
 
        if (guess.Length != 4)
        {
            bulls := -1 
        }
        else
        {
            try
            {
                for (int i := 0, i < 4, i+=1) {
                    var ch := guess[i];
                    var number := ch.toString().toInt();
 
                    // check range
                    ifnot (number > 0 && number < 10)
                        { InvalidArgumentException.raise() };
 
                    // check duplicates
                    var duplicate := guess.seekEach:(x => (x == ch)&&(x.equalReference(ch).Inverted));
                    if (nil != duplicate)
                    {
                        InvalidArgumentException.raise()
                    };
 
                    if (number == theNumbers[i])
                    { 
                        bulls += 1 
                    }
                    else
                    {
                        if (theNumbers.ifExists(number))
                            { cows += 1 }
                    }
                }
            }
            catch(Exception e)
            {
                bulls := -1
            }
        };
 
        bulls =>
            -1 { console.printLine:"Not a valid guess."; ^ true }
             4 { console.printLine:"Congratulations! You have won!"; ^ false }
             : {
                 theAttempt.append(1);
 
                 console.printLine("Your Score is ",bulls," bulls and ",cows," cows");
 
                 ^ true
             }
    }
}
 
public program()
{
    var gameMaster := new GameMaster();
 
    (lazy:gameMaster.proceed(gameMaster.ask())).doWhile();
 
    console.readChar()
}