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


/*REXX program scores the   Bulls & Cows   game with  CBLFs  (Carbon Based Life Forms). */
?=; do  until length(?)==4;   r= random(1, 9)  /*generate a unique four-digit number.   */
    if pos(r,?)\==0  then iterate;  ?= ? || r  /*don't allow a repeated digit/numeral.  */
    end   /*until length*/                     /* [↑]  builds a unique four-digit number*/
$= '──────── [Bulls & Cows]  '                 /*a literal that is part of the prompt.  */
    do  until  bulls==4;      say              /*play until guessed  or  enters  "Quit".*/
    say $  'Please enter a 4-digit guess (with no zeroes)   [or Quit]:'
    pull n;  n=space(n, 0);   if abbrev('QUIT', n, 1)  then exit   /*user wants to quit?*/
    q=?;   L= length(n);   bulls= 0;   cows= 0 /*initialize some REXX variables.        */
        do j=1  for L;    if substr(n, j, 1)\==substr(q, j, 1)  then iterate  /*is bull?*/
        bulls= bulls +1;  q= overlay(., q, j)  /*bump the bull count;  disallow for cow.*/
        end   /*j*/                            /* [↑]  bull count───────────────────────*/
                                                                              /*is cow? */
        do k=1  for L;   _= substr(n, k, 1);           if pos(_, q)==0  then iterate
        cows=cows + 1;   q= translate(q, , _)  /*bump the cow count;  allow mult digits.*/
        end   /*k*/                            /* [↑]  cow  count───────────────────────*/
    say;                  @= 'You got'   bulls
    if L\==0  &  bulls\==4  then say $  @  'bull's(bulls)    "and"    cows   'cow's(cows).
    end   /*until bulls*/
                            say "          ┌─────────────────────────────────────────┐"
                            say "          │                                         │"
                            say "          │  Congratulations, you've guessed it !!  │"
                            say "          │                                         │"
                            say "          └─────────────────────────────────────────┘"
exit                                             /*stick a fork in it,  we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
s:  if arg(1)==1  then return '';   return "s"   /*this function handles pluralization. */