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


BC := proc(n) #where n is the number of turns the user wishes to play before they quit
	local target, win, numGuesses, guess, bulls, cows, i, err;
    	target := [0, 0, 0, 0]:
    	randomize(); #This is a command that makes sure that the numbers are truly randomized each time, otherwise your first time will always give the same result.
	while member(0, target) or numelems({op(target)}) < 4 do #loop continues to generate random numbers until you get one with no repeating digits or 0s
		target := [seq(parse(i), i in convert(rand(1234..9876)(), string))]: #a list of random numbers
	end do:
 
	win := false:
	numGuesses := 0:
	while win = false and numGuesses < n do #loop allows the user to play until they win or until a set amount of turns have passed
		err := true;
		while err do #loop asks for values until user enters a valid number
			printf("Please enter a 4 digit integer with no repeating digits\n");
			try#catches any errors in user input
				guess := [seq(parse(i), i in readline())];
				if hastype(guess, 'Not(numeric)', 'exclude_container') then
					printf("Postive integers only! Please guess again.\n\n");
				elif numelems(guess) <> 4 then
					printf("4 digit numbers only! Please guess again.\n\n");
				elif numelems({op(guess)}) < 4 then
					printf("No repeating digits! Please guess again.\n\n");
				elif member(0, guess) then
					printf("No 0s! Please guess again.\n\n");
				else 
					err := false;
				end if;
			catch:
				printf("Invalid input. Please guess again.\n\n");
			end try;
		end do:
		numGuesses := numGuesses + 1;
		printf("Guess %a: %a\n", numGuesses, guess);
		bulls := 0;
		cows := 0;
		for i to 4 do #loop checks for bulls and cows in the user's guess
			if target[i] = guess[i] then
				bulls := bulls + 1;
			elif member(target[i], guess) then
				cows := cows + 1;
			end if;
		end do;
		if bulls = 4 then
			win := true;
			printf("The number was %a.\n", target);
			printf(StringTools[FormatMessage]("You won with %1 %{1|guesses|guess|guesses}.", numGuesses));
		else
			printf(StringTools[FormatMessage]("%1 %{1|Cows|Cow|Cows}, %2 %{2|Bulls|Bull|Bulls}.\n\n", cows, bulls));
		end if;
	end do:
	if win = false and numGuesses >= n then
        printf("You lost! The number was %a.\n", target);
     end if;
	return NULL;
end proc: