Bulls and cows
From Rosetta Code
This is an old game played with pencil and paper that was later implemented on computer.
The task is for the program to 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, then 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.
[edit] Ada
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Numerics.Discrete_Random;
procedure Bulls_And_Cows is
package Random_Natural is new Ada.Numerics.Discrete_Random (Natural);
Number : String (1..4);
begin
declare -- Generation of number
use Random_Natural;
Digit : String := "123456789";
Size : Positive := 9;
Dice : Generator;
Position : Natural;
begin
Reset (Dice);
for I in Number'Range loop
Position := Random (Dice) mod Size + 1;
Number (I) := Digit (Position);
Digit (Position..Size - 1) := Digit (Position + 1..Size);
Size := Size - 1;
end loop;
end;
loop -- Guessing loop
Put ("Enter four digits:");
declare
Guess : String := Get_Line;
Bulls : Natural := 0;
Cows : Natural := 0;
begin
if Guess'Length /= 4 then
raise Data_Error;
end if;
for I in Guess'Range loop
for J in Number'Range loop
if Guess (I) not in '1'..'9' or else (I < J and then Guess (I) = Guess (J)) then
raise Data_Error;
end if;
if Number (I) = Guess (J) then
if I = J then
Bulls := Bulls + 1;
else
Cows := Cows + 1;
end if;
end if;
end loop;
end loop;
exit when Bulls = 4;
Put_Line (Integer'Image (Bulls) & " bulls," & Integer'Image (Cows) & " cows");
exception
when Data_Error => Put_Line ("You should enter four different digits 1..9");
end;
end loop;
end Bulls_And_Cows;
[edit] ALGOL 68
Translation of: Python
Works with: ALGOL 68 version Standard - no extensions to language used
Works with: ALGOL 68G version Any - tested with release mk15-0.8b.fc9.i386
Works with: ELLA ALGOL 68 version Any (with appropriate job cards) - tested with release 1.8.8d.fc9.i386
STRING digits = "123456789";
[4]CHAR chosen;
STRING available := digits;
FOR i TO UPB chosen DO
INT c = ENTIER(random*UPB available)+1;
chosen[i] := available[c];
available := available[:c-1]+available[c+1:]
OD;
COMMENT print((chosen, new line)); # Debug # END COMMENT
OP D = (INT d)STRING: whole(d,0); # for formatting an integer #
print (("I have chosen a number from ",D UPB chosen," unique digits from 1 to 9 arranged in a random order.", new line,
"You need to input a ",D UPB chosen," digit, unique digit number as a guess at what I have chosen", new line));
PRIO WITHIN = 5, NOTWITHIN = 5;
OP WITHIN = (CHAR c, []CHAR s)BOOL: char in string(c,LOC INT,s);
OP NOTWITHIN = (CHAR c, []CHAR s)BOOL: NOT ( c WITHIN s );
INT guesses := 0, bulls, cows;
WHILE
STRING guess;
guesses +:= 1;
WHILE
# get a good guess #
print((new line,"Next guess [",D guesses,"]: "));
read((guess, new line));
IF UPB guess NE UPB chosen THEN
FALSE
ELSE
BOOL ok;
FOR i TO UPB guess WHILE
ok := guess[i] WITHIN digits AND guess[i] NOTWITHIN guess[i+1:]
DO SKIP OD;
NOT ok
FI
DO
print(("Problem, try again. You need to enter ",D UPB chosen," unique digits from 1 to 9", new line))
OD;
# WHILE #
guess NE chosen
DO
bulls := cows := 0;
FOR i TO UPB chosen DO
IF guess[i] = chosen[i] THEN
bulls +:= 1
ELIF guess[i] WITHIN chosen THEN
cows +:= 1
FI
OD;
print((" ",D bulls," Bulls",new line," ",D cows," Cows"));
OD;
print((new line, "Congratulations you guessed correctly in ",D guesses," attempts.",new line))
[edit] AutoHotkey
While StrLen(Code) < 4 {
Random, num, 1, 9
If !InStr(Code, num)
Code .= num
}
Gui, Add, Edit, vGuess, Enter a guess...
Gui, Add, Button, wp Default, Submit
Gui, Add, ListBox, ym r8 vHistory
Gui, Show
Return
ButtonSubmit:
Gui, Submit, NoHide
If StrLen(Guess) != 4
Return
If Guess is not digit
Return
bulls:=0, cows:=0
Loop, 4
If (SubStr(Guess, A_Index, 1) = SubStr(Code, A_Index, 1))
bulls++
Else If InStr(Code, SubStr(Guess, A_Index, 1))
cows++
GuiControl,, History, % Guess ": " bulls " Bulls " cows " Cows"
Return
GuiClose:
ExitApp
[edit] BASIC
Works with: FreeBASIC
DIM secret AS String
DIM guess AS String
DIM c AS String
DIM AS Integer bulls, cows, guesses, i
RANDOMIZE
DO WHILE LEN(secret) < 4
c = CHR$(INT(RND*10) + 48)
IF INSTR(secret, c) = 0 THEN secret = secret+c
LOOP
guesses = 0
DO
INPUT "Guess a 4-digit number with no duplicate digits: "; guess
IF LEN(guess) = 0 THEN EXIT DO
IF LEN(guess) <> 4 OR VAL(guess) = 0 THEN
PRINT "** You should enter 4 numeric digits!"
CONTINUE DO
END IF
bulls=0: cows=0: guesses = guesses+1
FOR i = 1 TO 4
c = MID$(secret, i, 1)
IF MID$(guess, i, 1) = c THEN
bulls = bulls+1
ELSEIF INSTR(guess, c) THEN
cows = cows+1
END IF
NEXT i
PRINT bulls; " bulls, "; cows; " cows"
IF guess = secret THEN
PRINT "You won after "; guesses; " guesses!"
EXIT DO
END IF
LOOP
[edit] C
Library: ncurses
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdbool.h>
#include <curses.h>
#include <string.h>
#define MAX_NUM_TRIES 72
#define LINE_BEGIN 7
#define LAST_LINE 18
int yp=LINE_BEGIN, xp=0;
char number[5];
char guess[5];
#define MAX_STR 256
void mvaddstrf(int y, int x, const char *fmt, ...)
{
va_list args;
char buf[MAX_STR];
va_start(args, fmt);
vsprintf(buf, fmt, args);
move(y, x);
clrtoeol();
addstr(buf);
va_end(args);
}
void ask_for_a_number()
{
int i=0;
char symbols[] = "123456789";
move(5,0); clrtoeol();
addstr("Enter four digits: ");
while(i<4) {
int c = getch();
if ( (c >= '1') && (c <= '9') && (symbols[c-'1']!=0) ) {
addch(c);
symbols[c-'1'] = 0;
guess[i++] = c;
}
}
}
void choose_the_number()
{
int i=0, j;
char symbols[] = "123456789";
while(i<4) {
j = rand() % 9;
if ( symbols[j] != 0 ) {
number[i++] = symbols[j];
symbols[j] = 0;
}
}
}
The following function contains the code to check how many bulls and cows there are.
bool take_it_or_not()
{
int i;
int cows=0, bulls=0;
for(i=0; i < 4; i++) {
if ( number[i] == guess[i] ) {
bulls++;
} else if ( strchr(number, guess[i]) != NULL ) {
cows++;
}
}
move(yp, xp);
addstr(guess); addch(' ');
if ( bulls == 4 ) { yp++; return true; }
if ( (cows==0) && (bulls==0) ) addch('-');
while( cows-- > 0 ) addstr("O");
while( bulls-- > 0 ) addstr("X");
yp++;
if ( yp > LAST_LINE ) {
yp = LINE_BEGIN;
xp += 10;
}
return false;
}
bool ask_play_again()
{
int i;
while(yp-- >= LINE_BEGIN) {
move(yp, 0); clrtoeol();
}
yp = LINE_BEGIN; xp = 0;
move(21,0); clrtoeol();
addstr("Do you want to play again? [y/n]");
while(true) {
int a = getch();
switch(a) {
case 'y':
case 'Y':
return true;
case 'n':
case 'N':
return false;
}
}
}
int main()
{
bool bingo, again;
int tries = 0;
initscr(); cbreak(); noecho();
clear();
number[4] = guess[4] = 0;
mvaddstr(0,0, "I choose a number made of 4 digits (from 1 to 9) without repetitions\n"
"You enter a number of 4 digits, and I say you how many of them are\n"
"in my secret number but in wrong position (cows or O), and how many\n"
"are in the right position (bulls or X)");
do {
move(20,0); clrtoeol(); move(21, 0); clrtoeol();
srand(time(NULL));
choose_the_number();
do {
ask_for_a_number();
bingo = take_it_or_not();
tries++;
} while(!bingo && (tries < MAX_NUM_TRIES));
if ( bingo )
mvaddstrf(20, 0, "You guessed %s correctly in %d attempts!", number, tries);
else
mvaddstrf(20,0, "Sorry, you had only %d tries...; the number was %s",
MAX_NUM_TRIES, number);
again = ask_play_again();
tries = 0;
} while(again);
nocbreak(); echo(); endwin();
return EXIT_SUCCESS;
}
[edit] C++
#include <iostream>
#include <string>
#include <algorithm>
#include <cstdlib>
bool contains_duplicates(std::string s)
{
std::sort(s.begin(), s.end());
return std::adjacent_find(s.begin(), s.end()) != s.end();
}
void game()
{
typedef std::string::size_type index;
std::string symbols = "0123456789";
int const selection_length = 4;
std::random_shuffle(symbols.begin(), symbols.end());
std::string selection = symbols.substr(0, selection_length);
std::string guess;
while (std::cout << "Your guess? ", std::getline(std::cin, guess))
{
if (guess.length() != selection_length
|| guess.find_first_not_of(symbols) != std::string::npos
|| contains_duplicates(s))
{
std::cout << guess << " is not a valid guess!";
continue;
}
int bulls = 0;
int cows = 0;
for (index i = 0; i != selection_length; ++i)
{
index pos = selection.find(guess[i]);
if (pos == i)
++bulls;
else if (pos != std::string::npos)
++cows;
}
std::cout << bulls << " bulls, " << cows << " cows.\n";
if (bulls == selection_length)
{
std::cout << "Congratulations! You have won!\n";
return:
}
}
std::cerr << "Oops! Something went wrong with input, or you've entered end-of-file!\nExiting ...\n";
std::exit(EXIT_FAILURE);
}
int main()
{
std::cout << "Welcome to bulls and cows!\nDo you want to play? ";
std::string answer;
while (true)
{
while (true)
{
if (!std::getline(std::cin, answer))
{
std::cout << "I can't get an answer. Exiting.\n";
return EXIT_FAILURE;
}
if (answer == "yes" || answer == "Yes" || answer == "y" || answer == "Y")
break;
if (answer == "no" || answer == "No" || answer == "n" || answer == "N")
{
std::cout << "Ok. Goodbye.\n";
return EXIT_SUCCESS;
}
std::cout << "Please answer yes or no: ";
}
game();
std::cout << "Another game? ";
}
}
[edit] Clojure
(ns bulls-and-cows
(:import (java.util Random Scanner)))
(let [generator (Random.)]
(defn pick [xs]
"Randomly pick an element of xs."
(nth xs (.nextInt generator (count xs)))))
(defn pick-n-unique [n xs]
"Randomly pick n elements of xs. Every xs can only be picked once."
(loop [picked []]
(if (= (count picked) n)
picked
(recur (conj picked (pick (remove (set picked) xs)))))))
(defn bulls [guess sol]
(count (filter true? (map = guess sol))))
(defn cows [guess sol]
(count (filter (set sol) guess)))
(let [scanner (Scanner. *in*)]
(defn enter-guess []
"Let the user enter a guess. Verify the input. Repeat until valid."
(print "Enter your guess: ") (flush)
(let [guess (.nextLine scanner)]
(if (or (not= (count guess) 4)
(not-every? #(Character/isDigit %1) guess)
(not= (distinct guess) (seq guess)))
(recur)
(map #(Character/digit % 10) guess)))))
(defn bulls-and-cows []
(let [solution (pick-n-unique 4 (range 1 10))]
(loop [guess (enter-guess)]
(println (bulls guess solution) " bulls and " (cows guess solution) " cows.")
(if (not= guess solution)
(recur (enter-guess))
(println "You have won!")))))
(bulls-and-cows)
[edit] Common Lisp
(defun get-number ()
(do ((digits '()))
((>= (length digits) 4) digits)
(pushnew (1+ (random 9)) digits)))
(defun compute-score (guess number)
(let ((cows 0)
(bulls 0))
(map nil (lambda (guess-digit number-digit)
(cond ((= guess-digit number-digit) (incf bulls))
((member guess-digit number) (incf cows))))
guess number)
(values cows bulls)))
(defun number->guess (number)
(when (integerp number)
(do ((digits '()))
((zerop number) digits)
(multiple-value-bind (quotient remainder) (floor number 10)
(push remainder digits)
(setf number quotient)))))
(defun valid-guess-p (guess)
(and (= 4 (length guess))
(every (lambda (digit) (<= 1 digit 9)) guess)
(equal guess (remove-duplicates guess))))
(defun play-game (&optional (stream *query-io*))
(do ((number (get-number))
(cows 0)
(bulls 0))
((= 4 bulls))
(format stream "~&Guess a 4-digit number: ")
(let ((guess (number->guess (read stream))))
(cond ((not (valid-guess-p guess))
(format stream "~&Malformed guess."))
(t
(setf (values cows bulls) (compute-score guess number))
(if (= 4 bulls)
(format stream "~&Correct, you win!")
(format stream "~&Score: ~a cows, ~a bulls."
cows bulls)))))))
[edit] E
Note: This example was deliberately written in an abstracted style, separating out the algorithms, game logic, and UI.
def Digit := 1..9
def Number := Tuple[Digit,Digit,Digit,Digit]
/** Choose a random number to be guessed. */
def pick4(entropy) {
def digits := [1,2,3,4,5,6,7,8,9].diverge()
# Partial Fisher-Yates shuffle
for i in 0..!4 {
def other := entropy.nextInt(digits.size() - i) + i
def t := digits[other]
digits[other] := digits[i]
digits[i] := t
}
return digits(0, 4)
}
/** Compute the score of a guess. */
def scoreGuess(actual :Number, guess :Number) {
var bulls := 0
var cows := 0
for i => digit in guess {
if (digit == actual[i]) {
bulls += 1
} else if (actual.indexOf1(digit) != -1) {
cows += 1
}
}
return [bulls, cows]
}
/** Parse a guess string into a list of digits (Number). */
def parseGuess(guessString, fail) :Number {
if (guessString.size() != 4) {
return fail(`I need four digits, not ${guessString.size()} digits.`)
} else {
var digits := []
for c in guessString {
if (('1'..'9')(c)) {
digits with= c - '0'
} else {
return fail(`I need a digit from 1 to 9, not "$c".`)
}
}
return digits
}
}
/** The game loop: asking for guesses and reporting scores and win conditions.
The return value is null or a broken reference if there was a problem. */
def bullsAndCows(askUserForGuess, tellUser, entropy) {
def actual := pick4(entropy)
def gameTurn() {
return when (def guessString := askUserForGuess <- ()) -> {
escape tellAndContinue {
def guess := parseGuess(guessString, tellAndContinue)
def [bulls, cows] := scoreGuess(actual, guess)
if (bulls == 4) {
tellUser <- (`You got it! The number is $actual!`)
null
} else {
tellAndContinue(`Your score for $guessString is $bulls bulls and $cows cows.`)
}
} catch message {
# The parser or scorer has something to say, and the game continues afterward
when (tellUser <- (message)) -> {
gameTurn()
}
}
} catch p {
# Unexpected problem of some sort
tellUser <- ("Sorry, game crashed.")
throw(p)
}
}
return gameTurn()
}
[edit] REPL user interface
def replBullsAndCows() {
when (
bullsAndCows(fn {
def [guess, env] := e`def guess; guess`.evalToPair(interp.getTopScope().nestOuter())
interp.setTopScope(env)
println("Please type “ bind guess := \"your guess here\" ”.")
guess
}, println, entropy)
) -> {} catch p {
println(`$p${p.eStack()}`)
}
}
[edit] Graphical user interface
Works with: E-on-Java (Java Swing)
def guiBullsAndCows() {
var lastGuess := ""
def op := <unsafe:javax.swing.makeJOptionPane>
return bullsAndCows(fn {
lastGuess := op.showInputDialog(null, "Enter your guess:", lastGuess)
if (lastGuess == null) {
# canceled, so just fail to return an answer and let the game logic get GCed
Ref.promise()[0]
} else {
lastGuess
}
}, fn msg {
op.showMessageDialog(null, msg)
}, entropy)
}
[edit] Factor
USING: accessors assocs combinators fry grouping hashtables kernel
locals math math.parser math.ranges random sequences strings
io ascii ;
IN: bullsncows
TUPLE: score bulls cows ;
: <score> ( -- score ) 0 0 score boa ;
TUPLE: cow ;
: <cow> ( -- cow ) cow new ;
TUPLE: bull ;
: <bull> ( -- bull ) bull new ;
: inc-bulls ( score -- score ) dup bulls>> 1 + >>bulls ;
: inc-cows ( score -- score ) dup cows>> 1 + >>cows ;
: random-nums ( -- seq ) 9 [1,b] 4 sample ;
: add-digits ( seq -- n ) 0 [ swap 10 * + ] reduce number>string ;
: new-number ( -- n narr ) random-nums dup add-digits ;
: narr>nhash ( narr -- nhash ) { 1 2 3 4 } swap zip ;
: num>hash ( n -- hash )
[ 1string string>number ] { } map-as narr>nhash ;
:: cow-or-bull ( n g -- arr )
{
{ [ n first g at n second = ] [ <bull> ] }
{ [ n second g value? ] [ <cow> ] }
[ f ]
} cond ;
: add-to-score ( arr -- score )
<score> [ bull? [ inc-bulls ] [ inc-cows ] if ] reduce ;
: check-win ( score -- ? ) bulls>> 4 = ;
: sum-score ( n g -- score ? )
'[ _ cow-or-bull ] map sift add-to-score dup check-win ;
: print-sum ( score -- str )
dup bulls>> number>string "Bulls: " swap append swap cows>> number>string
" Cows: " swap 3append "\n" append ;
: (validate-readln) ( str -- ? ) dup length 4 = not swap [ letter? ] all? or ;
: validate-readln ( -- str )
readln dup (validate-readln)
[ "Invalid input.\nPlease enter a valid 4 digit number: "
write flush drop validate-readln ]
when ;
: win ( -- ) "\nYou've won! Good job. You're so smart." print flush ;
: main-loop ( x -- )
"Enter a 4 digit number: " write flush validate-readln num>hash swap
[ sum-score swap print-sum print flush ] keep swap not
[ main-loop ] [ drop win ] if ;
: main ( -- ) new-number drop narr>nhash main-loop ;
[edit] Fan
**
** Bulls and cows. A game pre-dating, and similar to, Mastermind.
**
class BullsAndCows
{
Void main()
{
digits := [1,2,3,4,5,6,7,8,9]
size := 4
chosen := [,]
size.times { chosen.add(digits.removeAt(Int.random(0..<digits.size))) }
echo("I've chosen $size unique digits from 1 to 9 at random.
Try to guess my number!")
guesses := 0
while (true) // game loop
{
guesses += 1
guess := Int[,]
while (true) // input loop
{
// get a good guess
Sys.out.print("\nNext guess [$guesses]: ")
Sys.out.flush
inString := Sys.in.readLine?.trim ?: ""
inString.each |ch|
{ if (ch >= '1' && ch <= '9' && !guess.contains(ch)) guess.add(ch-'0') }
if (guess.size == 4)
break // input loop
echo("Oops, try again. You need to enter $size unique digits from 1 to 9")
}
if (guess.all |v, i->Bool| { return v == chosen[i] })
{
echo("\nCongratulations! You guessed correctly in $guesses guesses")
break // game loop
}
bulls := 0
cows := 0
(0 ..< size).each |i|
{
if (guess[i] == chosen[i])
bulls += 1
else if (chosen.contains(guess[i]))
cows += 1
}
echo("\n $bulls Bulls\n $cows Cows")
}
}
}
[edit] Forth
Works with: GNU Forth
include random.fs
create hidden 4 allot
: ok? ( str -- ? )
dup 4 <> if 2drop false exit then
1 9 lshift 1- -rot
bounds do
i c@ '1 -
dup 0 9 within 0= if 2drop false leave then
1 swap lshift over and
dup 0= if nip leave then
xor
loop 0<> ;
: init
begin
hidden 4 bounds do 9 random '1 + i c! loop
hidden 4 ok?
until ;
: check? ( addr -- solved? )
0
4 0 do
over i + c@
4 0 do
dup hidden i + c@ = if swap
i j = if 8 else 1 then + swap
then
loop drop
loop nip
8 /mod tuck . ." bulls, " . ." cows"
4 = ;
: guess: ( "1234" -- )
bl parse 2dup ok? 0= if 2drop ." Bad guess! (4 unique digits, 1-9)" exit then
drop check? if cr ." You guessed it!" then ;
init ok guess: 1234 1 bulls, 0 cows ok guess: 1567 1 bulls, 1 cows ok guess: 1895 2 bulls, 1 cows ok guess: 1879 4 bulls, 0 cows You guessed it! ok
[edit] Fortran
Works with: Fortran version 90 and later
module bac
implicit none
contains
subroutine Gennum(n)
integer, intent(out) :: n(4)
integer :: i, j
real :: r
call random_number(r)
n(1) = int(r * 9.0) + 1
i = 2
outer: do while (i <= 4)
call random_number(r)
n(i) = int(r * 9.0) + 1
inner: do j = i-1 , 1, -1
if (n(j) == n(i)) cycle outer
end do inner
i = i + 1
end do outer
end subroutine Gennum
subroutine Score(n, guess, b, c)
character(*), intent(in) :: guess
integer, intent(in) :: n(0:3)
integer, intent(out) :: b, c
integer :: digit, i, j, ind
b = 0; c = 0
do i = 1, 4
read(guess(i:i), "(i1)") digit
if (digit == n(i-1)) then
b = b + 1
else
do j = i, i+2
ind = mod(j, 4)
if (digit == n(ind)) then
c = c + 1
exit
end if
end do
end if
end do
end subroutine Score
end module bac
program Bulls_and_Cows
use bac
implicit none
integer :: n(4)
integer :: bulls=0, cows=0, tries=0
character(4) :: guess
call random_seed
call Gennum(n)
write(*,*) "I have selected a number made up of 4 digits (1-9) without repetitions."
write(*,*) "You attempt to guess this number."
write(*,*) "Every digit in your guess that is in the correct position scores 1 Bull"
write(*,*) "Every digit in your guess that is in an incorrect position scores 1 Cow"
write(*,*)
do while (bulls /= 4)
write(*,*) "Enter a 4 digit number"
read*, guess
if (verify(guess, "123456789") /= 0) then
write(*,*) "That is an invalid entry. Please try again."
cycle
end if
tries = tries + 1
call Score (n, guess, bulls, cows)
write(*, "(a, i1, a, i1, a)") "You scored ", bulls, " bulls and ", cows, " cows"
write(*,*)
end do
write(*,"(a,i0,a)") "Congratulations! You correctly guessed the correct number in ", tries, " attempts"
end program Bulls_and_Cows
[edit] Go
package main
import (
. "fmt";
"rand";
"time";
"os";
"bufio";
"strconv";
"strings";
)
func generateTarget() int {
rand.Seed(time.Nanoseconds());
// loop until we find a number that doesn't have dupes
for {
target := rand.Intn(9000) + 1000;
if !hasDupes(target) {
return target
}
}
panic("Crap.");
}
func hasDupes(num int) bool {
digs := make([]bool, 10);
for num > 0 {
if digs[num%10] {
return true
}
digs[num%10] = true;
num /= 10;
}
return false;
}
func askForNumber() (int, os.Error) {
in := bufio.NewReader(os.Stdin);
for {
Printf("Give me a number: ");
line, err := in.ReadString('\n');
if err != nil {
return -1, err
}
// Strip off the \n
line = line[0 : len(line)-1];
number, err := strconv.Atoi(line);
switch {
case err != nil:
Println("Give me a number fule!")
case number < 1000:
Println("Number not long enough")
case number > 9999:
Println("Number is to big")
case hasDupes(number):
Println("I said no dupes!")
default:
return number, nil
}
// Keep Asking
}
panic("Crap.");
}
func bullsAndCows(number int, guess int) (bulls int, cows int) {
bulls, cows = 0, 0;
numberstr := strconv.Itoa(number);
guessstr := strconv.Itoa(guess);
for i, _ := range guessstr {
s := string(guessstr[i]);
switch {
case guessstr[i] == numberstr[i]:
bulls++
case strings.Index(numberstr, s) >= 0:
cows++
}
}
return;
}
func main() {
attempts := 0;
Printf("I choose a number made of 4 digits (from 1 to 9) without repetitions\n"
"You enter a number of 4 digits, and I say you how many of them are\n"
"in my secret number but in wrong position (cows or O), and how many\n"
"are in the right position (bulls or X)\n\n");
target := generateTarget();
for {
guess, err := askForNumber();
attempts++;
// Handle err
if err != nil && err != os.EOF {
Printf("%v", err)
} else if err == os.EOF {
return
}
// Check if target matches guess
if guess == target {
Printf("Congratulations you guessed correctly in %v attempts\n", attempts);
return;
}
bulls, cows := bullsAndCows(target, guess);
Printf("%v Bulls, %v Cows\n", bulls, cows);
}
}
[edit] Haskell
import Data.List (partition, intersect, nub)
import Control.Monad
import System.Random (StdGen, getStdRandom, randomR)
import Text.Printf
numberOfDigits = 4 :: Int
main = bullsAndCows
bullsAndCows :: IO ()
bullsAndCows = do
digits <- getStdRandom $ pick numberOfDigits ['1' .. '9']
putStrLn "Guess away!"
loop digits
where loop digits = do
input <- getLine
if okay input
then
let (bulls, cows) = score digits input in
if bulls == numberOfDigits then
putStrLn "You win!"
else do
printf "%d bulls, %d cows.\n" bulls cows
loop digits
else do
putStrLn "Malformed guess; try again."
loop digits
okay :: String -> Bool
okay input =
length input == numberOfDigits &&
input == nub input &&
all legalchar input
where legalchar c = '1' <= c && c <= '9'
score :: String -> String -> (Int, Int)
score secret guess = (length bulls, cows)
where (bulls, nonbulls) = partition (uncurry (==)) $
zip secret guess
cows = length $ uncurry intersect $ unzip nonbulls
pick :: Int -> [a] -> StdGen -> ([a], StdGen)
{- Randomly selects items from a list without replacement. -}
pick n l g = f n l g (length l - 1) []
where f 0 _ g _ ps = (ps, g)
f n l g max ps =
f (n - 1) (left ++ right) g' (max - 1) (picked : ps)
where (i, g') = randomR (0, max) g
(left, picked : right) = splitAt i l
[edit] J
require 'misc'
plural=: conjunction define
(":m),' ',n,'s'#~1~:m
)
bullcow=:monad define
number=. 1+4?9
guess=._
while.-.guess-:number do.
guess=.0 "."0 prompt 'Guess my number: '
if. (4~:#guess)+.(4~:#~.guess)+.0 e.guess e.1+i.9 do.
if.0=#guess do.
smoutput 'Giving up.'
return.
end.
smoutput 'Guesses must be four different non-zero digits'
continue.
end.
bulls=. +/guess=number
cows=. (+/guess e.number)-bulls
smoutput bulls plural 'bull',' and ',cows plural 'cow','.'
end.
smoutput 'you win'
)
[edit] Java
import java.util.InputMismatchException;
import java.util.Random;
import java.util.Scanner;
public class BullsAndCows{
public static void main(String[] args){
Random gen= new Random();
int target= 0;
while(hasDupes(target= (gen.nextInt(9000) + 1000)));
String targetStr = target +"";
boolean guessed = false;
Scanner input = new Scanner(System.in);
int guesses = 0;
do{
int bulls = 0;
int cows = 0;
System.out.print("Guess a 4-digit number with no duplicate digits: ");
int guess;
try{
guess = input.nextInt();
if(hasDupes(guess) || guess < 1000) continue;
}catch(InputMismatchException e){
continue;
}
guesses++;
String guessStr = guess + "";
for(int i= 0;i < 4;i++){
if(guessStr.charAt(i) == targetStr.charAt(i)){
bulls++;
}else if(targetStr.contains(guessStr.charAt(i)+"")){
cows++;
}
}
if(bulls == 4){
guessed = true;
}else{
System.out.println(cows+" Cows and "+bulls+" Bulls.");
}
}while(!guessed);
System.out.println("You won after "+guesses+" guesses!");
}
public static boolean hasDupes(int num){
boolean[] digs = new boolean[10];
while(num > 0){
if(digs[num%10]) return true;
digs[num%10] = true;
num/= 10;
}
return false;
}
}
Output:
Guess a 4-digit number with no duplicate digits: 5834 2 Cows and 0 Bulls. Guess a 4-digit number with no duplicate digits: 1234 1 Cows and 0 Bulls. Guess a 4-digit number with no duplicate digits: 4321 1 Cows and 0 Bulls. Guess a 4-digit number with no duplicate digits: 3421 0 Cows and 1 Bulls. Guess a 4-digit number with no duplicate digits: 8412 0 Cows and 0 Bulls. Guess a 4-digit number with no duplicate digits: 3560 1 Cows and 1 Bulls. Guess a 4-digit number with no duplicate digits: 3650 0 Cows and 2 Bulls. Guess a 4-digit number with no duplicate digits: 3759 2 Cows and 2 Bulls. Guess a 4-digit number with no duplicate digits: 3975 2 Cows and 2 Bulls. Guess a 4-digit number with no duplicate digits: 3957 You won after 10 guesses!
[edit] Logo
Works with: UCB Logo
to ok? :n
output (and [number? :n] [4 = count :n] [4 = count remdup :n] [not member? 0 :n])
end
to init
do.until [make "hidden random 10000] [ok? :hidden]
end
to guess :n
if not ok? :n [print [Bad guess! (4 unique digits, 1-9)] stop]
localmake "bulls 0
localmake "cows 0
foreach :n [cond [
[[? = item # :hidden] make "bulls 1 + :bulls]
[[member? ? :hidden] make "cows 1 + :cows ]
]]
(print :bulls "bulls, :cows "cows)
if :bulls = 4 [print [You guessed it!]]
end
[edit] MUMPS
BullCow New bull,cow,guess,guessed,ii,number,pos,x
Set number="",x=1234567890
For ii=1:1:4 Do
. Set pos=$Random($Length(x))+1
. Set number=number_$Extract(x,pos)
. Set $Extract(x,pos)=""
. Quit
Write !,"The computer has selected a number that consists"
Write !,"of four different digits."
Write !!,"As you are guessing the number, ""bulls"" and ""cows"""
Write !,"will be awarded: a ""bull"" for each digit that is"
Write !,"placed in the correct position, and a ""cow"" for each"
Write !,"digit that occurs in the number, but in a different place.",!
Write !,"For a guess, enter 4 digits."
Write !,"Any other input is interpreted as ""I give up"".",!
Set guessed=0 For Do Quit:guessed
. Write !,"Your guess: " Read guess If guess'?4n Set guessed=-1 Quit
. Set (bull,cow)=0,x=guess
. For ii=4:-1:1 If $Extract(x,ii)=$Extract(number,ii) Do
. . Set bull=bull+1,$Extract(x,ii)=""
. . Quit
. For ii=1:1:$Length(x) Set:number[$Extract(x,ii) cow=cow+1
. Write !,"You guessed ",guess,". That earns you "
. If 'bull,'cow Write "neither bulls nor cows..." Quit
. If bull Write bull," bull" Write:bull>1 "s"
. If cow Write:bull " and " Write cow," cow" Write:cow>1 "s"
. Write "."
. If bull=4 Set guessed=1 Write !,"That's a perfect score."
. Quit
If guessed<0 Write !!,"The number was ",number,".",!
Quit
Do BullCow
The computer has selected a number that consists
of four different digits.
As you are guessing the number, "bulls" and "cows"
will be awarded: a "bull" for each digit that is
placed in the correct position, and a "cow" for each
digit that occurs in the number, but in a different place.
For a guess, enter 4 digits.
Any other input is interpreted as "I give up".
Your guess: 1234
You guessed 1234. That earns you 1 cow.
Your guess: 5678
You guessed 5678. That earns you 1 cow.
Your guess: 9815
You guessed 9815. That earns you 1 cow.
Your guess: 9824
You guessed 9824. That earns you 2 cows.
Your guess: 9037
You guessed 9037. That earns you 1 bull and 2 cows.
Your guess: 9048
You guessed 2789. That earns you 1 bull and 2 cows.
Your guess: 2079
You guessed 2079. That earns you 1 bull and 3 cows.
Your guess: 2709
You guessed 2709. That earns you 2 bulls and 2 cows.
Your guess: 0729
You guessed 0729. That earns you 4 cows.
Your guess: 2907
You guessed 2907. That earns you 4 bulls.
That's a perfect score.
[edit] OCaml
let rec input() =
let s = read_line () in
try
if String.length s <> 4 then raise Exit;
String.iter (function
| '1'..'9' -> ()
| _ -> raise Exit
) s;
let t = [ s.[0]; s.[1]; s.[2]; s.[3] ] in
let _ = List.fold_left (* reject entry with duplication *)
(fun ac b -> if List.mem b ac then raise Exit; (b::ac))
[] t in
List.map (fun c -> int_of_string (String.make 1 c)) t
with Exit ->
prerr_endline "That is an invalid entry. Please try again.";
input()
;;
let print_score g t =
let bull = ref 0 in
List.iter2 (fun x y ->
if x = y then incr bull
) g t;
let cow = ref 0 in
List.iter (fun x ->
if List.mem x t then incr cow
) g;
cow := !cow - !bull;
Printf.printf "%d bulls, %d cows\n%!" !bull !cow
;;
let () =
Random.self_init();
let rec mkgoal acc = function 4 -> acc
| i ->
let n = succ(Random.int 9) in
if List.mem n acc
then mkgoal acc i
else mkgoal (n::acc) (succ i)
in
let g = mkgoal [] 0 in
let found = ref false in
while not !found do
let t = input() in
if t = g
then found := true
else print_score g t
done;
print_endline "Congratulations you guessed correctly";
;;
[edit] Oz
declare
proc {Main}
Solution = {PickNUnique 4 {List.number 1 9 1}}
proc {Loop}
Guess = {EnterGuess}
in
{System.showInfo
{Bulls Guess Solution}#" bulls and "#
{Cows Guess Solution}#" cows"}
if Guess \= Solution then {Loop} end
end
in
{Loop}
{System.showInfo "You have won!"}
end
fun {Bulls Xs Sol}
{Length {Filter {List.zip Xs Sol Value.'=='} Id}}
end
fun {Cows Xs Sol}
{Length {Intersection Xs Sol}}
end
local
class TextFile from Open.file Open.text end
StdIn = {New TextFile init(name:stdin)}
in
fun {EnterGuess}
try
{System.printInfo "Enter your guess (e.g. \"1234\"): "}
S = {StdIn getS($)}
in
%% verify
{Length S} = 4
{All S Char.isDigit} = true
{FD.distinct S} %% assert there is no duplicate digit
%% convert from digits to numbers
{Map S fun {$ D} D-&0 end}
catch _ then
{EnterGuess}
end
end
end
fun {PickNUnique N Xs}
{FoldL {MakeList N}
fun {$ Z _}
{Pick {Diff Xs Z}}|Z
end
nil}
end
fun {Pick Xs}
{Nth Xs {OS.rand} mod {Length Xs} + 1}
end
fun {Diff Xs Ys}
{FoldL Ys List.subtract Xs}
end
fun {Intersection Xs Ys}
{Filter Xs fun {$ X} {Member X Ys} end}
end
fun {Id X} X end
in
{Main}
[edit] Perl
use Data::Random qw(rand_set);
use List::MoreUtils qw(uniq);
my $size = 4;
my $chosen = join "", rand_set set => ["1".."9"], size => $size;
print "I've chosen a number from $size unique digits from 1 to 9; you need
to input $size unique digits to guess my number\n";
for ( my $guesses = 1; ; $guesses++ ) {
my $guess;
while (1) {
print "\nNext guess [$guesses]: ";
$guess = <STDIN>;
chomp $guess;
checkguess($guess) and last;
print "$size digits, no repetition, no 0... retry\n";
}
if ( $guess eq $chosen ) {
print "You did it in $guesses attempts!\n";
last;
}
my $bulls = 0;
my $cows = 0;
for my $i (0 .. $size-1) {
if ( substr($guess, $i, 1) eq substr($chosen, $i, 1) ) {
$bulls++;
} elsif ( index($chosen, substr($guess, $i, 1)) >= 0 ) {
$cows++;
}
}
print "$cows cows, $bulls bulls\n";
}
sub checkguess
{
my $g = shift;
return uniq(split //, $g) == $size && $g =~ /^[1-9]{$size}$/;
}
[edit] Perl 6
Translation of: Python
Works with: Rakudo version #22 "Thousand Oaks"
constant SIZE = 4;
my @secret = pick SIZE, '1' .. '9';
my $guesses = 0;
loop {
++$guesses;
my ($bulls, $cows, @guess) = 0, 0;
loop {
print "Guess $guesses: ";
@guess = split *, $*IN.get;
@guess == SIZE
and all(@guess) eq one(@guess) & any('1' .. '9')
and last;
say 'Malformed guess; try again.';
}
for ^SIZE {
when @guess[$_] eq @secret[$_] { ++$bulls; }
when @guess[$_] eq any @secret { ++$cows; }
}
$bulls == SIZE and last;
say "$bulls bulls, $cows cows.";
}
say 'A winner is you!';
[edit] PHP
<?php
$size = 4;
$chosen = implode(array_rand(array_flip(range(1,9)), $size));
echo "I've chosen a number from $size unique digits from 1 to 9; you need
to input $size unique digits to guess my number\n";
for ($guesses = 1; ; $guesses++) {
while (true) {
echo "\nNext guess [$guesses]: ";
$guess = rtrim(fgets(STDIN));
if (!checkguess($guess))
echo "$size digits, no repetition, no 0... retry\n";
else
break;
}
if ($guess == $chosen) {
echo "You did it in $guesses attempts!\n";
break;
} else {
$bulls = 0;
$cows = 0;
foreach (range(0, $size-1) as $i) {
if ($guess[$i] == $chosen[$i])
$bulls++;
else if (strpos($chosen, $guess[$i]) !== FALSE)
$cows++;
}
echo "$cows cows, $bulls bulls\n";
}
}
function checkguess($g)
{
global $size;
return count(array_unique(str_split($g))) == $size &&
preg_match("/^[1-9]{{$size}}$/", $g);
}
?>
[edit] PicoLisp
(de ok? (N)
(let D (mapcar 'format (chop N))
(and (num? N)
(not (member 0 D))
(= 4 (length D))
(= D (uniq D))
D )) )
(de init-cows ()
(until (setq *Hidden (ok? (rand 1234 9876)))) )
(de guess (N)
(let D (ok? N)
(if D
(let Bulls (cnt '= D *Hidden)
(if (= 4 Bulls)
" You guessed it!"
(let Cows (- (cnt '((N) (member N *Hidden)) D) Bulls)
(pack Bulls " bulls, " Cows " cows") ) ) )
" Bad guess! (4 unique digits, 1-9)" ) ) )
[edit] PureBasic
Define.s secret, guess, c
Define.i bulls, cows, guesses, i
If OpenConsole()
While Len(secret) < 4
c = Chr(Random(8) + 49)
If FindString(secret, c, 1) = 0
secret + c
EndIf
Wend
Repeat
Print("Guess a 4-digit number with no duplicate digits: ")
guess = Input()
If Len(guess) = 0
Break ;break from loop
EndIf
isMalformedGuess = #False
If Len(guess) <> 4
;guess is too short
isMalformedGuess = #True
Else
For i = 1 To 4
c = Mid(guess, i, 1)
If Not FindString("123456789", c, 1) Or CountString(guess, c) <> 1
;guess contains either non-digits or duplicate digits
isMalformedGuess = #True
Break ;break from For/Next loop
EndIf
Next
EndIf
If isMalformedGuess
PrintN("** You should enter 4 different numeric digits that are each from 1 to 9!")
Continue ;continue loop
EndIf
bulls = 0: cows = 0: guesses = guesses + 1
For i = 1 To 4
c = Mid(secret, i, 1)
If Mid(guess, i, 1) = c
bulls + 1
ElseIf FindString(guess, c, 1)
cows + 1
EndIf
Next
Print( Str(bulls) + " bull")
If bulls <> 1
Print( "s")
EndIf
Print( ", " + Str(cows) + " cow")
If cows <> 1
PrintN( "s")
Else
PrintN("")
EndIf
If guess = secret
PrintN("You won after " + Str(guesses) + " guesses!")
Break ;break from loop
EndIf
ForEver
Print(#CRLF$ + #CRLF$ + "Press ENTER to exit")
Input()
CloseConsole()
EndIf
[edit] Python
'''
Bulls and cows. A game pre-dating, and similar to, Mastermind.
'''
import random
digits = '123456789'
size = 4
chosen = ''.join(random.sample(digits,size))
#print chosen # Debug
print '''I have chosen a number from %s unique digits from 1 to 9 arranged in a random order.
You need to input a %i digit, unique digit number as a guess at what I have chosen''' % (size, size)
guesses = 0
while True:
guesses += 1
while True:
# get a good guess
guess = raw_input('\nNext guess [%i]: ' % guesses).strip()
if len(guess) == size and \
all(char in digits for char in guess) \
and len(set(guess)) == size:
break
print "Problem, try again. You need to enter %i unique digits from 1 to 9" % size
if guess == chosen:
print '\nCongratulations you guessed correctly in',guesses,'attempts'
break
bulls = cows = 0
for i in range(size):
if guess[i] == chosen[i]:
bulls += 1
elif guess[i] in chosen:
cows += 1
print ' %i Bulls\n %i Cows' % (bulls, cows)
Sample output:
I have chosen a number from 4 unique digits from 1 to 9 arranged in a random order. You need to input a 4 digit, unique digit number as a guess at what I have chosen Next guess [1]: 79 Problem, try again. You need to enter 4 unique digits from 1 to 9 Next guess [1]: 7983 2 Bulls 2 Cows Next guess [2]: 7938 Congratulations you guessed correctly in 2 attempts
[edit] R
Works with: R version 2.8.1
target <- sample(1:9,4)
bulls <- 0
cows <- 0
attempts <- 0
while (bulls != 4)
{
input <- readline("Guess a 4-digit number with no duplicate digits or 0s: ")
if (nchar(input) == 4)
{
input <- as.integer(strsplit(input,"")[[1]])
if ((sum(is.na(input)+sum(input==0))>=1) | (length(table(input)) != 4)) {print("Malformed input!")} else {
bulls <- sum(input == target)
cows <- sum(input %in% target)-bulls
cat("\n",bulls," Bull(s) and ",cows, " Cow(s)\n")
attempts <- attempts + 1
}
} else {print("Malformed input!")}
}
print(paste("You won in",attempts,"attempt(s)!"))
[edit] Ruby
Inspired by Tcl Works with: Ruby version 1.8.7+
def generate_word(len)
([1, 2, 3, 4, 5, 6, 7, 8, 9].shuffle)[0,len].join("")
end
def get_guess(len)
while true
print "Enter a guess: "
guess = gets.strip
err = case
when guess.match(/\D/) : "digits only"
when guess.length != len : "exactly #{len} digits"
when guess.split("").uniq.length != len: "digits must be unique "
else nil
end
break if err.nil?
puts "the word must be #{len} unique digits between 1 and 9 (#{err}). Try again."
end
guess
end
def score(word, guess)
bulls = cows = 0
guess.bytes.each_with_index do |byte, idx|
if word[idx] == byte
bulls += 1
elsif word.include? byte
cows += 1
end
end
[bulls, cows]
end
srand
word_length = 4
puts "I have chosen a number with #{word_length} unique digits from 1 to 9."
word = generate_word(word_length)
count = 0
while true
guess = get_guess(word_length)
count += 1
break if word == guess
puts "that guess has %d bulls and %d cows" % score(word, guess)
end
puts "you guessed correctly in #{count} tries."
[edit] Smalltalk
Works with: GNU Smalltalk
Object subclass: BullsCows [
|number|
BullsCows class >> new: secretNum [ |i|
i := self basicNew.
(self isValid: secretNum)
ifFalse: [ SystemExceptions.InvalidArgument
signalOn: secretNum
reason: 'You need 4 unique digits from 1 to 9' ].
i setNumber: secretNum.
^ i
]
BullsCows class >> new [ |b| b := Set new.
[ b size < 4 ]
whileTrue: [ b add: ((Random between: 1 and: 9) displayString first) ].
^ self new: (b asString)
]
BullsCows class >> isValid: num [
^ (num asSet size = 4) & ((num asSet includes: $0) not)
]
setNumber: num [ number := num ]
check: guess [ |bc| bc := Bag new.
1 to: 4 do: [ :i |
(number at: i) = (guess at: i)
ifTrue: [ bc add: 'bulls' ]
ifFalse: [
(number includes: (guess at: i))
ifTrue: [ bc add: 'cows' ]
]
].
^ bc
]
].
'Guess the 4-digits number (digits from 1 to 9, no repetition)' displayNl.
|guessMe d r tries|
[
tries := 0.
guessMe := BullsCows new.
[
[
'Write 4 digits: ' display.
d := stdin nextLine.
(BullsCows isValid: d)
] whileFalse: [
'Insert 4 digits, no repetition, exclude the digit 0' displayNl
].
r := guessMe check: d.
tries := tries + 1.
(r occurrencesOf: 'bulls') = 4
] whileFalse: [
('%1 cows, %2 bulls' % { r occurrencesOf: 'cows'. r occurrencesOf: 'bulls' })
displayNl.
].
('Good, you guessed it in %1 tries!' % { tries }) displayNl.
'Do you want to play again? [y/n]' display.
( (stdin nextLine) = 'y' )
] whileTrue: [ Character nl displayNl ].
[edit] Tcl
proc main {} {
fconfigure stdout -buffering none
set length 4
puts "I have chosen a number from $length unique digits from 1 to 9 arranged in a random order.
You need to input a $length digit, unique digit number as a guess at what I have chosen
"
while true {
set word [generateWord $length]
set count 1
while {[set guess [getGuess $length]] ne $word} {
printScore $length $word $guess
incr count
}
puts "You guessed correctly in $count tries."
if {[yn "Play again?"] eq "n"} break
}
}
proc generateWord {length} {
set chars 123456789
for {set i 1} {$i <= $length} {incr i} {
set idx [expr {int(rand() * [string length $chars])}]
append word [string index $chars $idx]
set chars [string replace $chars $idx $idx]
}
return $word
# here's another way to generate word with no duplications
set word ""
while {[string length $word] < $length} {
set char [expr {int(1 + 9*rand())}]
if {[string first $char $word] == -1} {
append word $char
}
}
}
proc getGuess {length} {
puts -nonewline "Enter your guess: "
while true {
gets stdin guess
if {[string match [string repeat {[1-9]} $length] $guess]} {
return $guess
}
if {[string tolower [string trim $guess]] eq "quit"} {
puts Bye
exit
}
puts "The word must be $length digits between 1 and 9 inclusive. Try again."
}
}
proc printScore {length word guess} {
set bulls 0
set cows 0
for {set i 0} {$i < $length} {incr i} {
if {[string index $word $i] eq [string index $guess $i]} {
incr bulls
set word [string replace $word $i $i +]
}
}
puts " $bulls bulls"
for {set i 0} {$i < $length} {incr i} {
if {[set j [string first [string index $guess $i] $word]] != -1} {
incr cows
set word [string replace $word $j $j -]
}
}
puts " $cows cows"
}
proc yn {msg} {
while true {
puts -nonewline "$msg \[y/n] "
gets stdin ans
set char [string tolower [string index [string trim $ans] 0]]
if {$char eq "y" || $char eq "n"} {
return $char
}
}
}
main
[edit] Vedit macro language
Buf_Switch(Buf_Free)
#90 = Time_Tick // seed for random number generator
#91 = 10 // random numbers in range 0 to 9
while (EOB_pos < 4) { // 4 digits needed
Call("RANDOM")
BOF Ins_Char(Return_Value + '0')
Replace("(.)(.*)\1", "\1\2", REGEXP+BEGIN+NOERR) // remove any duplicate
}
#3 = 0
repeat (99) {
Get_Input(10, "Guess a 4-digit number with no duplicate digits: ", NOCR)
if (Reg_Size(10) == 0) { Break } // empty string = exit
Num_Eval_Reg(10) // check for numeric digits
if (Chars_Matched != 4) {
M("You should enter 4 numeric digits\n")
Continue
}
Goto_Pos(4) // count bulls
Reg_Ins(10, OVERWRITE)
#1 = Search("(.)...\1", REGEXP+BEGIN+ALL+NOERR)
RS(10, "[", INSERT) // count cows
RS(10, "]", APPEND)
#2 = Search_Block(@10, 0, 4, REGEXP+BEGIN+ALL+NOERR) - #1
#3++
NT(#1, NOCR) M(" bulls,") NT(#2, NOCR) M(" cows\n")
if (#1 == 4) {
M("You won after") NT(#3, NOCR) M(" guesses!\n")
Break
}
}
Buf_Quit(OK)
Return
//--------------------------------------------------------------
// Generate random numbers in range 0 <= Return_Value < #91
// #90 = Seed (0 to 0x7fffffff)
// #91 = Scaling (0 to 0x10000)
:RANDOM:
#92 = 0x7fffffff / 48271
#93 = 0x7fffffff % 48271
#90 = (48271 * (#90 % #92) - #93 * (#90 / #92)) & 0x7fffffff
Return ((#90 & 0xffff) * #91 / 0x10000)
[edit] Visual Basic .NET
Imports System
Imports System.Text.RegularExpressions
Module Bulls_and_Cows
Function CreateNumber() As String
Dim random As New Random()
Dim sequence As Char() = {"1"c, "2"c, "3"c, "4"c, "5"c, "6"c, "7"c, "8"c, "9"c}
For i As Integer = 0 To sequence.Length - 1
Dim j As Integer = random.Next(sequence.Length)
Dim temp As Char = sequence(i) : sequence(i) = sequence(j) : sequence(j) = temp
Next
Return New String(sequence, 0, 4)
End Function
Function IsFourDigitNumber(ByVal number As String) As Boolean
Return Regex.IsMatch(number, "^[1-9]{4}$")
End Function
Sub Main()
Dim chosenNumber As String = CreateNumber()
Dim attempt As Integer = 0
Console.WriteLine("Number is chosen")
Dim gameOver As Boolean = False
Do
attempt += 1
Console.WriteLine("Attempt #{0}. Enter four digit number: ", attempt)
Dim number As String = Console.ReadLine()
Do While Not IsFourDigitNumber(number)
Console.WriteLine("Invalid number: type four characters. Every character must digit be between '1' and '9'.")
number = Console.ReadLine()
Loop
Dim bulls As Integer = 0
Dim cows As Integer = 0
For i As Integer = 0 To number.Length - 1
Dim j As Integer = chosenNumber.IndexOf(number(i))
If i = j Then
bulls += 1
ElseIf j >= 0 Then
cows += 1
End If
Next
If bulls < chosenNumber.Length Then
Console.WriteLine("The number '{0}' has {1} bulls and {2} cows", _
number, bulls, cows)
Else
gameOver = True
End If
Loop Until gameOver
Console.WriteLine("The number was guessed in {0} attempts. Congratulations!", attempt)
End Sub
End Module







