Bulls and cows: Difference between revisions
No edit summary Tags: Mobile edit Mobile web edit |
|||
(356 intermediate revisions by more than 100 users not shown) | |||
Line 1: | Line 1: | ||
[[Category:Puzzles]] |
|||
[[Category:Games]] |
|||
{{task|Games}} |
{{task|Games}} |
||
[[wp:Bulls and Cows|This]] is an old game played with pencil and paper that was later implemented on computer. |
|||
[[wp:Bulls and Cows|Bulls and Cows]] is an old game played with pencil and paper that was later implemented using computers. |
|||
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. |
|||
;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 score is computed as: |
||
Line 9: | Line 19: | ||
# 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 '''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. |
# 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]] |
|||
<br><br> |
|||
=={{header|8080 Assembly}}== |
|||
This is written to run under CP/M and includes an RNG to generate the secret. |
|||
<syntaxhighlight lang="8080asm">bdos equ 5 |
|||
putchar equ 2 |
|||
rawio equ 6 |
|||
puts equ 9 |
|||
cstat equ 11 |
|||
reads equ 10 |
|||
org 100h |
|||
mvi c,puts |
|||
lxi d,signon ; Print name |
|||
call bdos |
|||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
|||
;; Initialize the RNG with keyboard input |
|||
mvi c,puts |
|||
lxi d,entropy ; Ask for randomness |
|||
call bdos |
|||
mvi b,9 ; 9 times, |
|||
randloop: mvi c,3 ; read 3 keys. |
|||
lxi h,xabcdat + 1 |
|||
randkey: push b ; Read a key |
|||
push h |
|||
randkeywait: mvi c,rawio |
|||
mvi e,0FFh |
|||
call bdos |
|||
ana a |
|||
jz randkeywait |
|||
pop h |
|||
pop b |
|||
xra m ; XOR it with the random memory |
|||
mov m,a |
|||
inx h |
|||
dcr c |
|||
jnz randkey ; Go get more characters |
|||
dcr b |
|||
jnz randloop |
|||
mvi c,puts |
|||
lxi d,done ; Tell the user we're done |
|||
call bdos |
|||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
|||
;; Generate 4-digit secret code |
|||
lxi h,secret |
|||
mvi b,4 |
|||
gencode: push h |
|||
push b |
|||
call randcode |
|||
pop b |
|||
pop h |
|||
mov m,a |
|||
inx h |
|||
dcr b |
|||
jnz gencode |
|||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
|||
;; User makes a guess |
|||
readguess: mvi c,puts ; Ask for guess |
|||
lxi d,guess |
|||
call bdos |
|||
mvi c,reads ; Read guess |
|||
lxi d,bufdef |
|||
call bdos |
|||
call newline ; Print newline |
|||
mvi b,4 ; Check input |
|||
lxi h,buf |
|||
validate: mov a,m |
|||
cpi '9' + 1 ; >9? |
|||
jnc inval ; = invalid |
|||
cpi '1' ; <1? |
|||
jc inval ; = invalid |
|||
sui '0' ; Make ASCII digit into number |
|||
mov m,a |
|||
inx h |
|||
dcr b |
|||
jnz validate |
|||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
|||
;; Count bulls |
|||
mvi c,puts |
|||
lxi d,bulls ; Output "Bulls:" |
|||
call bdos |
|||
lxi d,secret |
|||
lxi h,buf |
|||
lxi b,4 ; No bulls, counter = 4 |
|||
bullloop: ldax d ; Get secret digit |
|||
cmp m ; Match to buffer digit |
|||
cz countmatch |
|||
inx h |
|||
inx d |
|||
dcr c |
|||
jnz bullloop |
|||
push b ; Keep bulls for cow count, |
|||
push b ; and for final check. |
|||
call printcount |
|||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
|||
;; Count cows |
|||
mvi c,puts |
|||
lxi d,cows ; Output ", Cows:" |
|||
call bdos |
|||
pop psw ; Retrieve the bulls (into A reg) |
|||
cma ; Negate amount of bulls |
|||
inr a |
|||
mov b,a ; Use it as start of cow count |
|||
mvi d,4 ; For all 4 secret digits.. |
|||
lxi h,secret |
|||
cowouter: mov a,m ; Grab secret digit to test |
|||
push h ; Store secret position |
|||
mvi e,4 ; For all 4 input digits... |
|||
lxi h,buf |
|||
cowinner: cmp m ; Compare to current secret digit |
|||
cz countmatch |
|||
inx h |
|||
dcr e ; While there are more digits in buf |
|||
jnz cowinner ; Test next digit |
|||
pop h ; Restore secret position |
|||
inx h ; Look at next secret digit |
|||
dcr d ; While there are digits left |
|||
jnz cowouter |
|||
push b ; Keep cow count |
|||
call printcount |
|||
call newline |
|||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
|||
;; Check win condition |
|||
pop psw ; Cow count (in A) |
|||
pop b ; Bull count (in B) |
|||
ana a ; To win, there must be 0 cows... |
|||
jnz readguess |
|||
mvi a,4 ; And 4 bulls. |
|||
cmp b |
|||
jnz readguess |
|||
mvi c,puts |
|||
lxi d,win |
|||
jmp bdos |
|||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
|||
;; Increment bull/cow counter |
|||
countmatch: inr b |
|||
ret |
|||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
|||
;; Print a newline |
|||
newline: mvi c,puts |
|||
lxi d,nl |
|||
jmp bdos |
|||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
|||
;; Output counter as ASCII |
|||
printcount: mvi a,'0' |
|||
add b |
|||
mvi c,putchar |
|||
mov e,a |
|||
jmp bdos |
|||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
|||
;; User entered invalid input |
|||
inval: mvi c,puts |
|||
lxi d,invalid |
|||
call bdos |
|||
jmp readguess |
|||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
|||
;; Generate random number 1-9 that isn't in key |
|||
randcode: call xabcrand |
|||
ani 0fh ; Low nybble |
|||
ana a ; 0 = invalid |
|||
jz randcode |
|||
cpi 10 ; >9 = invalid |
|||
jnc randcode |
|||
;; Check if it is a duplicate |
|||
mvi b,4 |
|||
lxi h,secret |
|||
checkdup: cmp m |
|||
jz randcode |
|||
inx h |
|||
dcr b |
|||
jnz checkdup |
|||
ret |
|||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
|||
;; The "X ABC" 8-bit random number generator |
|||
;; (Google that to find where it came from) |
|||
xabcrand: lxi h,xabcdat |
|||
inr m ; X++ |
|||
mov a,m ; X, |
|||
inx h ; |
|||
xra m ; ^ C, |
|||
inx h ; |
|||
xra m ; ^ A, |
|||
mov m,a ; -> A |
|||
inx h |
|||
add m ; + B, |
|||
mov m,a ; -> B |
|||
rar ; >>1 |
|||
dcx h |
|||
xra m ; ^ A, |
|||
dcx h |
|||
add m ; + C |
|||
mov m,a ; -> C |
|||
ret |
|||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
|||
;; Strings |
|||
signon: db 'Bulls and Cows',13,10,'$' |
|||
entropy: db 'Please mash the keyboard to generate entropy...$' |
|||
done: db 'done.',13,10,13,10,'$' |
|||
bulls: db 'Bulls: $' |
|||
cows: db ', Cows: $' |
|||
guess: db 'Guess: $' |
|||
invalid: db 'Invalid input.',13,10,'$' |
|||
win: db 'You win!',13,10,'$' |
|||
nl: db 13,10,'$' |
|||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
|||
;; Variables |
|||
xabcdat: ds 4 ; RNG state |
|||
secret: ds 4 ; Holds the secret code |
|||
bufdef: db 4,0 ; User input buffer |
|||
buf: ds 4</syntaxhighlight> |
|||
=={{header|ABC}}== |
|||
<syntaxhighlight lang="ABC">HOW TO RETURN random.digit: |
|||
RETURN choice "123456789" |
|||
HOW TO MAKE SECRET secret: |
|||
PUT "" IN secret |
|||
FOR i IN {1..4}: |
|||
PUT random.digit IN digit |
|||
WHILE SOME j IN {1..i-1} HAS secret item j = digit: |
|||
PUT random.digit IN digit |
|||
PUT secret^digit IN secret |
|||
HOW TO RETURN guess count.bulls secret: |
|||
PUT 0 IN bulls |
|||
FOR i IN {1..4}: |
|||
IF secret item i = guess item i: PUT bulls+1 IN bulls |
|||
RETURN bulls |
|||
HOW TO RETURN guess count.cows secret: |
|||
PUT -(guess count.bulls secret) IN cows |
|||
FOR c IN guess: |
|||
IF c in secret: PUT cows+1 IN cows |
|||
RETURN cows |
|||
HOW TO REPORT has.duplicates guess: |
|||
FOR i IN {1..3}: |
|||
FOR j IN {i+1..4}: |
|||
IF guess item i = guess item j: SUCCEED |
|||
FAIL |
|||
HOW TO REPORT is.valid guess: |
|||
IF SOME digit IN guess HAS digit not.in "123456789": |
|||
WRITE "Invalid digit: ", digit/ |
|||
FAIL |
|||
IF #guess <> 4: |
|||
WRITE "Guess must contain 4 digits."/ |
|||
FAIL |
|||
IF has.duplicates guess: |
|||
WRITE "No duplicates allowed"/ |
|||
FAIL |
|||
SUCCEED |
|||
HOW TO READ GUESS guess: |
|||
WHILE 1=1: |
|||
WRITE "Guess? " |
|||
READ guess RAW |
|||
IF is.valid guess: QUIT |
|||
HOW TO PLAY BULLS AND COWS: |
|||
PUT 0, 0, 0 IN tries, bulls, cows |
|||
MAKE SECRET secret |
|||
WRITE "Bulls and cows"/ |
|||
WRITE "--------------"/ |
|||
WRITE / |
|||
WHILE bulls<>4: |
|||
READ GUESS guess |
|||
PUT guess count.bulls secret IN bulls |
|||
PUT guess count.cows secret IN cows |
|||
WRITE "Bulls:",bulls,"- Cows:",cows/ |
|||
PUT tries+1 IN tries |
|||
WRITE "You win! Tries:", tries |
|||
PLAY BULLS AND COWS</syntaxhighlight> |
|||
{{out}} |
|||
<pre>Bulls and cows |
|||
-------------- |
|||
Guess? 1234 |
|||
Bulls: 0 - Cows: 1 |
|||
Guess? 5678 |
|||
Bulls: 0 - Cows: 2 |
|||
Guess? 1679 |
|||
Bulls: 0 - Cows: 2 |
|||
Guess? 1689 |
|||
Bulls: 0 - Cows: 2 |
|||
Guess? 1659 |
|||
Bulls: 1 - Cows: 2 |
|||
Guess? 2659 |
|||
Bulls: 1 - Cows: 2 |
|||
Guess? 3659 |
|||
Bulls: 1 - Cows: 3 |
|||
Guess? 9356 |
|||
Bulls: 4 - Cows: 0 |
|||
You win! Tries: 8</pre> |
|||
=={{header|Action!}}== |
|||
<syntaxhighlight lang="action!">DEFINE DIGNUM="4" |
|||
TYPE Score=[BYTE bulls,cows,err] |
|||
PROC Generate(CHAR ARRAY secret) |
|||
DEFINE DIGCOUNT="9" |
|||
CHAR ARRAY digits(DIGCOUNT) |
|||
BYTE i,j,d,tmp,count |
|||
FOR i=0 TO DIGCOUNT-1 |
|||
DO |
|||
digits(i)=i+'1 |
|||
OD |
|||
secret(0)=DIGNUM |
|||
count=DIGCOUNT |
|||
FOR i=1 TO DIGNUM |
|||
DO |
|||
d=Rand(count) |
|||
secret(i)=digits(d) |
|||
count==-1 |
|||
digits(d)=digits(count) |
|||
OD |
|||
RETURN |
|||
PROC CheckScore(CHAR ARRAY code,guess Score POINTER res) |
|||
BYTE i,j |
|||
res.bulls=0 |
|||
res.cows=0 |
|||
IF guess(0)#DIGNUM THEN |
|||
res.err=1 |
|||
RETURN |
|||
FI |
|||
res.err=0 |
|||
FOR i=1 TO DIGNUM |
|||
DO |
|||
IF guess(i)=code(i) THEN |
|||
res.bulls==+1 |
|||
ELSE |
|||
FOR j=1 TO DIGNUM |
|||
DO |
|||
IF j#i AND guess(j)=code(i) THEN |
|||
res.cows==+1 |
|||
EXIT |
|||
FI |
|||
OD |
|||
FI |
|||
OD |
|||
RETURN |
|||
PROC Main() |
|||
CHAR ARRAY code(DIGNUM+1),guess(255) |
|||
Score res |
|||
Generate(code) |
|||
PrintE("Bull and cows game.") PutE() |
|||
Print("I choose a 4-digit number from digits 1 to 9 without repetition. ") |
|||
PrintE("Your goal is to guess it.") PutE() |
|||
PrintE("Enter your guess:") |
|||
DO |
|||
InputS(guess) |
|||
CheckScore(code,guess,res) |
|||
Put(28) ;cursor up |
|||
PrintF("%S -> ",guess) |
|||
IF res.err THEN |
|||
Print("Wrong input") |
|||
ELSE |
|||
PrintF("Bulls=%B Cows=%B",res.bulls,res.cows) |
|||
IF res.bulls=DIGNUM THEN |
|||
PutE() PutE() |
|||
PrintE("You win!") |
|||
EXIT |
|||
FI |
|||
FI |
|||
PrintE(", try again:") |
|||
OD |
|||
RETURN</syntaxhighlight> |
|||
{{out}} |
|||
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/Bulls_and_cows.png Screenshot from Atari 8-bit computer] |
|||
<pre> |
|||
Bull and cows game. |
|||
I choose a 4-digit number from digits 1 to 9 without repetition. Your goal is to guess it. |
|||
Enter your guess: |
|||
12345 -> Wrong input, try again: |
|||
1234 -> Bulls=0 Cows=2, try again: |
|||
1243 -> Bulls=2 Cows=0, try again: |
|||
5643 -> Bulls=2 Cows=0, try again: |
|||
7843 -> Bulls=3 Cows=0, try again: |
|||
7943 -> Bulls=2 Cows=1, try again: |
|||
9843 -> Bulls=4 Cows=0 |
|||
You win! |
|||
</pre> |
|||
=={{header|Ada}}== |
=={{header|Ada}}== |
||
<syntaxhighlight lang="ada">with Ada.Text_IO; use Ada.Text_IO; |
|||
<lang Ada> |
|||
with Ada.Text_IO; use Ada.Text_IO; |
|||
with Ada.Numerics.Discrete_Random; |
with Ada.Numerics.Discrete_Random; |
||
Line 64: | Line 473: | ||
end; |
end; |
||
end loop; |
end loop; |
||
end Bulls_And_Cows; |
end Bulls_And_Cows;</syntaxhighlight> |
||
</lang> |
|||
=={{header|ALGOL 68}}== |
=={{header|ALGOL 68}}== |
||
{{trans|Python}} |
{{trans|Python}} |
||
{{works with|ALGOL 68| |
{{works with|ALGOL 68|Revision 1 - no extensions to language used}} |
||
{{works with|ALGOL 68G|Any - tested with release |
{{works with|ALGOL 68G|Any - tested with release [http://sourceforge.net/projects/algol68/files/algol68g/algol68g-1.18.0/algol68g-1.18.0-9h.tiny.el5.centos.fc11.i386.rpm/download 1.18.0-9h.tiny]}} |
||
{{works with|ELLA ALGOL 68|Any (with appropriate job cards) - tested with release 1.8.8d.fc9.i386}} |
{{works with|ELLA ALGOL 68|Any (with appropriate job cards) - tested with release [http://sourceforge.net/projects/algol68/files/algol68toc/algol68toc-1.8.8d/algol68toc-1.8-8d.fc9.i386.rpm/download 1.8-8d]}} |
||
< |
<syntaxhighlight lang="algol68">STRING digits = "123456789"; |
||
[4]CHAR chosen; |
[4]CHAR chosen; |
||
Line 126: | Line 534: | ||
FI |
FI |
||
OD; |
OD; |
||
print((" ",D bulls," Bulls",new line," ",D cows," Cows")) |
print((" ",D bulls," Bulls",new line," ",D cows," Cows")) |
||
OD; |
OD; |
||
print((new line, "Congratulations you guessed correctly in ",D guesses," attempts.",new line))</ |
print((new line, "Congratulations you guessed correctly in ",D guesses," attempts.",new line))</syntaxhighlight> |
||
Output: |
|||
<pre> |
|||
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]: |
|||
</pre> |
|||
=={{header|APL}}== |
|||
{{works with|Dyalog APL}} |
|||
Call the <code>moo</code> function with one dummy argument to play a game of |
|||
Bulls and Cows in the APL session. |
|||
<syntaxhighlight lang="apl">input ← {⍞←'Guess: ' ⋄ 7↓⍞} |
|||
output ← {⎕←(↑'Bulls: ' 'Cows: '),⍕⍪⍵ ⋄ ⍵} |
|||
isdigits← ∧/⎕D∊⍨⊢ |
|||
valid ← isdigits∧4=≢ |
|||
guess ← ⍎¨input⍣(valid⊣) |
|||
bulls ← +/= |
|||
cows ← +/∊∧≠ |
|||
game ← (output ⊣(bulls,cows) guess)⍣(4 0≡⊣) |
|||
random ← 1+4?9⍨ |
|||
moo ← 'You win!'⊣(random game⊢) |
|||
</syntaxhighlight> |
|||
To show off APL, this is written entirely in tacit style (except for the I/O). There is no explicit flow control or recursion, |
|||
and there are no variables. The code is split into functions only to aid the reader, none is ever |
|||
referred to twice. The following definition of <code>moo</code> is exactly equivalent to the above: |
|||
<syntaxhighlight lang="apl">moo←'You win!'⊣((1+4?9⍨)(({⎕←(↑'Bulls: ' 'Cows: '),⍕⍪⍵⋄⍵}⊣((+/=),(+/∊∧≠))(⍎¨{⍞←'Guess: '⋄7↓⍞}⍣(((∧/⎕D∊⍨⊢)∧4=≢)⊣)))⍣(4 0≡⊣))⊢)</syntaxhighlight> |
|||
=={{header|AppleScript}}== |
|||
GUI implementation; the prompt for a guess includes a list of all past guesses and their scores. |
|||
<syntaxhighlight lang="applescript">on pickNumber() |
|||
set theNumber to "" |
|||
repeat 4 times |
|||
set theDigit to (random number from 1 to 9) as string |
|||
repeat while (offset of theDigit in theNumber) > 0 |
|||
set theDigit to (random number from 1 to 9) as string |
|||
end repeat |
|||
set theNumber to theNumber & theDigit |
|||
end repeat |
|||
end pickNumber |
|||
to bulls of theGuess given key:theKey |
|||
set bullCount to 0 |
|||
repeat with theIndex from 1 to 4 |
|||
if text theIndex of theGuess = text theIndex of theKey then |
|||
set bullCount to bullCount + 1 |
|||
end if |
|||
end repeat |
|||
return bullCount |
|||
end bulls |
|||
to cows of theGuess given key:theKey, bulls:bullCount |
|||
set cowCount to -bullCount |
|||
repeat with theIndex from 1 to 4 |
|||
if (offset of (text theIndex of theKey) in theGuess) > 0 then |
|||
set cowCount to cowCount + 1 |
|||
end if |
|||
end repeat |
|||
return cowCount |
|||
end cows |
|||
to score of theGuess given key:theKey |
|||
set bullCount to bulls of theGuess given key:theKey |
|||
set cowCount to cows of theGuess given key:theKey, bulls:bullCount |
|||
return {bulls:bullCount, cows:cowCount} |
|||
end score |
|||
on run |
|||
set theNumber to pickNumber() |
|||
set pastGuesses to {} |
|||
repeat |
|||
set theMessage to "" |
|||
repeat with aGuess in pastGuesses |
|||
set {theGuess, theResult} to aGuess |
|||
set theMessage to theMessage & theGuess & ":" & bulls of theResult & "B, " & cows of theResult & "C" & linefeed |
|||
end repeat |
|||
set theMessage to theMessage & linefeed & "Enter guess:" |
|||
set theGuess to text returned of (display dialog theMessage with title "Bulls and Cows" default answer "") |
|||
set theScore to score of theGuess given key:theNumber |
|||
if bulls of theScore is 4 then |
|||
display dialog "Correct! Found the secret in " & ((length of pastGuesses) + 1) & " guesses!" |
|||
exit repeat |
|||
else |
|||
set end of pastGuesses to {theGuess, theScore} |
|||
end if |
|||
end repeat |
|||
end run</syntaxhighlight> |
|||
=={{header|Arturo}}== |
|||
<syntaxhighlight lang="rebol">rand: first.n: 4 unique map 1..10 => [sample 0..9] |
|||
bulls: 0 |
|||
while [bulls <> 4][ |
|||
bulls: new 0 |
|||
cows: new 0 |
|||
got: strip input "make a guess: " |
|||
if? or? not? numeric? got |
|||
4 <> size got -> print "Malformed answer. Try again!" |
|||
else [ |
|||
loop.with:'i split got 'digit [ |
|||
if? (to :integer digit) = rand\[i] -> inc 'bulls |
|||
else [ |
|||
if contains? rand to :integer digit -> inc 'cows |
|||
] |
|||
] |
|||
print ["Bulls:" bulls "Cows:" cows "\n"] |
|||
] |
|||
] |
|||
print color #green "** Well done! You made the right guess!!"</syntaxhighlight> |
|||
=={{header|AutoHotkey}}== |
=={{header|AutoHotkey}}== |
||
<lang |
<syntaxhighlight lang="autohotkey">length:=4, Code:="" ; settings |
||
Random, num, 1, 9 |
|||
While StrLen(Code) < length { |
|||
If !InStr(Code, num) |
|||
Random, num, 1, 9 |
|||
Code .= num |
|||
If !InStr(Code, num) |
|||
Code .= num |
|||
} |
} |
||
Gui, Add, Text, w83 vInfo, I'm thinking of a %length%-digit number with no duplicate digits. |
|||
Gui, Add, Edit, vGuess, Enter a guess... |
|||
Gui, Add, |
Gui, Add, Edit, wp vGuess, Enter a guess... |
||
Gui, Add, |
Gui, Add, Button, wp Default vDefault, Submit |
||
Gui, Add, Edit, ym w130 r8 vHistory ReadOnly |
|||
Gui, Show |
Gui, Show |
||
Return |
Return |
||
ButtonSubmit: |
ButtonSubmit: |
||
If Default = Restart |
|||
Gui, Submit, NoHide |
|||
Reload |
|||
If StrLen(Guess) != 4 |
|||
Gui, Submit, NoHide |
|||
Return |
|||
If (StrLen(Guess) != length) |
|||
GuiControl, , Info, Enter a %length%-digit number. |
|||
Return |
|||
Else If Guess is not digit |
|||
bulls:=0, cows:=0 |
|||
GuiControl, , Info, Enter a %length%-digit number. |
|||
Loop, 4 |
|||
Else |
|||
If (SubStr(Guess, A_Index, 1) = SubStr(Code, A_Index, 1)) |
|||
{ |
|||
bulls++ |
|||
GuiControl, , Info |
|||
Else If InStr(Code, SubStr(Guess, A_Index, 1)) |
|||
GuiControl, , Guess |
|||
cows++ |
|||
If (Guess = Code) |
|||
GuiControl,, History, % Guess ": " bulls " Bulls " cows " Cows" |
|||
{ |
|||
GuiControl, , Info, Correct! |
|||
GuiControl, , Default, Restart |
|||
Default = Restart |
|||
} |
|||
response := Response(Guess, Code) |
|||
Bulls := SubStr(response, 1, InStr(response,",")-1) |
|||
Cows := SubStr(response, InStr(response,",")+1) |
|||
GuiControl, , History, % History . Guess ": " Bulls " Bulls " Cows " Cows`n" |
|||
} |
|||
Return |
Return |
||
GuiEscape: |
|||
GuiClose: |
GuiClose: |
||
ExitApp |
|||
</lang> |
|||
Response(Guess,Code) { |
|||
Bulls := 0, Cows := 0 |
|||
Loop, % StrLen(Code) |
|||
If (SubStr(Guess, A_Index, 1) = SubStr(Code, A_Index, 1)) |
|||
Bulls++ |
|||
Else If (InStr(Code, SubStr(Guess, A_Index, 1))) |
|||
Cows++ |
|||
Return Bulls "," Cows |
|||
}</syntaxhighlight> |
|||
=={{header|AWK}}== |
|||
<syntaxhighlight lang="awk"># Usage: GAWK -f BULLS_AND_COWS.AWK |
|||
BEGIN { |
|||
srand() |
|||
secret = "" |
|||
for (i = 1; i <= 4; ) { |
|||
digit = int(9 * rand()) + 1 |
|||
if (index(secret, digit) == 0) { |
|||
secret = secret digit |
|||
i++ |
|||
} |
|||
} |
|||
print "Welcome to 'Bulls and Cows'!" |
|||
print "I thought of a 4-digit number." |
|||
print "Please enter your guess." |
|||
} |
|||
iswellformed($0) { |
|||
if (calcscore($0, secret)) { |
|||
exit |
|||
} |
|||
} |
|||
function iswellformed(number, i, digit) { |
|||
if (number !~ /[1-9][1-9][1-9][1-9]/) { |
|||
print "Your guess should contain 4 digits, each from 1 to 9. Try again!" |
|||
return 0 |
|||
} |
|||
for (i = 1; i <= 3; i++) { |
|||
digit = substr(number, 1, 1) |
|||
number = substr(number, 2) |
|||
if (index(number, digit) != 0) { |
|||
print "Your guess contains a digit twice. Try again!" |
|||
return 0 |
|||
} |
|||
} |
|||
return 1 |
|||
} |
|||
function calcscore(guess, secret, bulls, cows, i, idx) { |
|||
# Bulls = correct digits at the right position |
|||
# Cows = correct digits at the wrong position |
|||
for (i = 1; i <= 4; i++) { |
|||
idx = index(secret, substr(guess, i, 1)) |
|||
if (idx == i) { |
|||
bulls++ |
|||
} else if (idx > 0) { |
|||
cows++ |
|||
} |
|||
} |
|||
printf("Your score for this guess: Bulls = %d, Cows = %d.", bulls, cows) |
|||
if (bulls < 4) { |
|||
printf(" Try again!\n") |
|||
} else { |
|||
printf("\nCongratulations, you win!\n") |
|||
} |
|||
return bulls == 4 |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Welcome to 'Bulls and Cows'! |
|||
I thought of a 4-digit number. |
|||
Please enter your guess. |
|||
1234 |
|||
Your score for this guess: Bulls = 0, Cows = 1. Try again! |
|||
5678 |
|||
Your score for this guess: Bulls = 1, Cows = 1. Try again! |
|||
9651 |
|||
Your score for this guess: Bulls = 1, Cows = 1. Try again! |
|||
5729 |
|||
Your score for this guess: Bulls = 0, Cows = 3. Try again! |
|||
2695 |
|||
Your score for this guess: Bulls = 2, Cows = 1. Try again! |
|||
2697 |
|||
Your score for this guess: Bulls = 2, Cows = 2. Try again! |
|||
7692 |
|||
Your score for this guess: Bulls = 4, Cows = 0. |
|||
Congratulations, you win! |
|||
</pre> |
|||
=={{header|BASIC}}== |
=={{header|BASIC}}== |
||
{{works with| |
{{works with|QBasic}} |
||
<syntaxhighlight lang="qbasic">DEFINT A-Z |
|||
<lang freebasic> |
|||
DIM secret AS String |
|||
DIM |
DIM secret AS STRING |
||
DIM |
DIM guess AS STRING |
||
DIM |
DIM c AS STRING |
||
DIM bulls, cows, guesses, i |
|||
RANDOMIZE |
RANDOMIZE TIMER |
||
DO WHILE LEN(secret) < 4 |
DO WHILE LEN(secret) < 4 |
||
c = CHR$(INT(RND*10) + 48) |
c = CHR$(INT(RND * 10) + 48) |
||
IF INSTR(secret, c) = 0 THEN secret = secret+c |
IF INSTR(secret, c) = 0 THEN secret = secret + c |
||
LOOP |
LOOP |
||
Line 178: | Line 801: | ||
DO |
DO |
||
INPUT "Guess a 4-digit number with no duplicate digits: "; guess |
INPUT "Guess a 4-digit number with no duplicate digits: "; guess |
||
guess = LTRIM$(RTRIM$(guess)) |
|||
IF LEN(guess) = 0 THEN EXIT DO |
IF LEN(guess) = 0 THEN EXIT DO |
||
IF LEN(guess) <> 4 OR VAL(guess) = 0 THEN |
IF LEN(guess) <> 4 OR VAL(guess) = 0 THEN |
||
PRINT "** You should enter 4 numeric digits!" |
PRINT "** You should enter 4 numeric digits!" |
||
GOTO looper |
|||
CONTINUE DO |
|||
END IF |
END IF |
||
bulls=0: cows=0: guesses = guesses+1 |
bulls = 0: cows = 0: guesses = guesses + 1 |
||
FOR i = 1 TO 4 |
FOR i = 1 TO 4 |
||
c = MID$(secret, i, 1) |
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 |
NEXT i |
||
PRINT bulls; " bulls, "; cows; " cows" |
PRINT bulls; " bulls, "; cows; " cows" |
||
Line 198: | Line 822: | ||
IF guess = secret THEN |
IF guess = secret THEN |
||
PRINT "You won after "; guesses; " guesses!" |
PRINT "You won after "; guesses; " guesses!" |
||
EXIT DO |
|||
END IF |
END IF |
||
looper: |
|||
LOOP |
|||
LOOP</syntaxhighlight> |
|||
</lang> |
|||
==={{header|Applesoft BASIC}}=== |
|||
<syntaxhighlight lang="applesoftbasic">100 D$ = "123456789" |
|||
110 FOR I = 1 TO 4 |
|||
120 P = INT(RND(1) * LEN(D$)) + 1 |
|||
130 N$ = N$ + MID$(D$, P, 1) |
|||
140 D$ = MID$(D$, 1, P - 1) + MID$(D$, P + 1, 8) |
|||
150 NEXT |
|||
160 PRINT "A RANDOM NUMBER HAS BEEN CREATED. |
|||
170 PRINT "THE NUMBER HAS FOUR DIGITS FROM 1 TO 9, WITHOUT DUPLICATION." |
|||
200 FOR Q = 0 TO 1 STEP 0 |
|||
210 INPUT "GUESS THE NUMBER: "; G% |
|||
220 G$ = STR$(G%) |
|||
230 M = LEN(G$) <> 4 OR G% = 0 |
|||
240 IF NOT M THEN FOR I = 2 TO 4 : M = MID$(G$, I, 1) = "0" : IF NOT M THEN NEXT I |
|||
250 IF NOT M THEN FOR I = 1 TO 3 : FOR J = I + 1 TO 4 : M = MID$(G$, I, 1) = MID$(G$, J, 1) : IF NOT M THEN NEXT J, I |
|||
260 IF M THEN PRINT "THE GUESS IS MALFORMED." : NEXT Q |
|||
270 B = 0 |
|||
280 C = 0 |
|||
300 FOR I = 1 TO 4 |
|||
310 C$ = MID$(N$, I, 1) |
|||
320 BULL = MID$(G$, I, 1) = C$ |
|||
330 COW = 0 |
|||
340 IF NOT BULL THEN FOR J = 1 TO 4 : COW = MID$(G$, J, 1) = C$ : IF NOT COW THEN NEXT J |
|||
350 B = B + BULL |
|||
360 C = C + COW |
|||
370 NEXT I |
|||
380 PRINT B " BULLS, " C " COWS" |
|||
390 Q = G$ = N$ |
|||
400 NEXT Q</syntaxhighlight> |
|||
==={{header|Commodore BASIC}}=== |
|||
Based on the AppleSoft BASIC version. Modifications as follows: |
|||
* Accommodate 80 character BASIC line length (for line 250 especially), created subroutines. |
|||
* Booleans in Commodore BASIC evaluate to -1 for TRUE, therefore ABS function added to give desired results. |
|||
* Leading space in printed numbers (which is placeholder for negative sign) is included in string conversion in Commodore BASIC, therefore RIGHT$ function added on 220 to trim leading whitespace upon conversion. |
|||
* Other formatting (clear screen, etc.) unique to Commodore BASIC. |
|||
<syntaxhighlight lang="freebasic">100 D$="123456789" |
|||
110 FOR I=1 TO 4 |
|||
120 P=INT(RND(1)*LEN(D$))+1 |
|||
130 N$=N$+MID$(D$,P,1) |
|||
140 D$=MID$(D$,1,P - 1)+MID$(D$,P+1,8) |
|||
150 NEXT |
|||
160 PRINT CHR$(147);"A RANDOM NUMBER HAS BEEN CREATED." |
|||
170 PRINT "THE NUMBER HAS FOUR DIGITS FROM 1 TO 9, WITHOUT DUPLICATION." |
|||
200 FOR Q=0 TO 1 STEP 0 |
|||
210 INPUT "GUESS THE NUMBER: "; G% |
|||
219 REM CONVERT TO STRING AND TRIM LEADING SPACE |
|||
220 G$=RIGHT$(STR$(G%),4) |
|||
230 M=LEN(G$)<>4 OR G%=0 |
|||
240 IF NOT M THEN GOSUB 600 |
|||
250 IF NOT M THEN GOSUB 700 |
|||
260 IF M THEN PRINT "THE GUESS IS MALFORMED.":NEXT Q |
|||
270 B=0 |
|||
280 C=0 |
|||
300 FOR I=1 TO 4 |
|||
310 C$=MID$(N$,I,1) |
|||
320 BULL=MID$(G$,I,1)=C$ |
|||
330 COW=0 |
|||
340 IF NOT BULL THEN FOR J=1 TO 4:COW=MID$(G$,J,1)=C$:IF NOT COW THEN NEXT J |
|||
350 B=B+ABS(BULL) |
|||
360 C=C+ABS(COW) |
|||
370 NEXT I |
|||
380 PRINT "BULLS:";B:PRINT "COWS:";C |
|||
390 Q=ABS(G$=N$) |
|||
400 NEXT Q |
|||
500 PRINT "GOOD JOB!":END |
|||
600 FOR I=2 TO 4:M=MID$(G$,I,1)="0" |
|||
610 IF NOT M THEN NEXT I |
|||
620 RETURN |
|||
700 FOR I=1 TO 3 |
|||
710 FOR J=I+1 TO 4 |
|||
720 M=MID$(G$,I,1)=MID$(G$,J,1) |
|||
730 IF NOT M THEN NEXT J,I |
|||
740 RETURN |
|||
</syntaxhighlight> |
|||
==={{header|IS-BASIC}}=== |
|||
<syntaxhighlight lang="is-basic">100 PROGRAM "Bulls.bas" |
|||
110 RANDOMIZE |
|||
120 STRING C$*4 |
|||
130 LET GUESS=0 |
|||
140 DO |
|||
150 LET C$=STR$(RND(8701)+1199) |
|||
160 LOOP UNTIL CHECK$(C$)=C$ |
|||
170 CLEAR SCREEN:PRINT "Welcome to 'Bulls and Cows!'" |
|||
180 DO |
|||
190 DO |
|||
200 PRINT :INPUT PROMPT "Guess a 4-digit number with no duplicate digits: ":G$ |
|||
210 IF CHECK$(G$)="" THEN PRINT "You should enter 4-digit number with no duplicate digits." |
|||
220 LOOP UNTIL CHECK$(G$)=G$ AND G$<>"" |
|||
230 LET GUESS=GUESS+1:LET BULLS,COWS=0 |
|||
240 FOR I=1 TO 4 |
|||
250 IF C$(I)=G$(I) THEN |
|||
260 LET BULLS=BULLS+1 |
|||
270 ELSE IF POS(C$,G$(I))<>0 THEN |
|||
280 LET COWS=COWS+1 |
|||
290 END IF |
|||
300 NEXT |
|||
310 PRINT BULLS;"bulls,";COWS;"cows" |
|||
320 LOOP UNTIL C$=G$ |
|||
330 PRINT "You won after";GUESS;"guesses!" |
|||
340 DEF CHECK$(S$) |
|||
350 LET CHECK$="" |
|||
360 IF LEN(STR$(VAL(S$)))=4 AND POS(S$,"0")=0 THEN LET CHECK$=S$ |
|||
370 FOR I=1 TO 4 |
|||
380 IF POS(S$(:I-1),S$(I)) OR POS(S$(I+1:),S$(I)) THEN LET CHECK$="" |
|||
390 NEXT |
|||
400 END DEF</syntaxhighlight> |
|||
==={{header|ZX Spectrum Basic}}=== |
|||
{{trans|QBasic}} |
|||
<syntaxhighlight lang="zxbasic">10 DIM n(10): LET c$="" |
|||
20 FOR i=1 TO 4 |
|||
30 LET d=INT (RND*9+1) |
|||
40 IF n(d)=1 THEN GO TO 30 |
|||
50 LET n(d)=1 |
|||
60 LET c$=c$+STR$ d |
|||
70 NEXT i |
|||
80 LET guesses=0 |
|||
90 INPUT "Guess a 4-digit number (1 to 9) with no duplicate digits: ";guess |
|||
100 IF guess=0 THEN STOP |
|||
110 IF guess>9999 OR guess<1000 THEN PRINT "Only 4 numeric digits, please": GO TO 90 |
|||
120 LET bulls=0: LET cows=0: LET guesses=guesses+1: LET g$=STR$ guess |
|||
130 FOR i=1 TO 4 |
|||
140 IF g$(i)=c$(i) THEN LET bulls=bulls+1: GO TO 160 |
|||
150 IF n(VAL g$(i))=1 THEN LET cows=cows+1 |
|||
160 NEXT i |
|||
170 PRINT bulls;" bulls, ";cows;" cows" |
|||
180 IF c$=g$ THEN PRINT "You won after ";guesses;" guesses!": GO TO 10 |
|||
190 GO TO 90 |
|||
</syntaxhighlight> |
|||
=={{header|Batch File}}== |
|||
<syntaxhighlight lang="dos">:: Bulls and Cows Task from Rosetta Code |
|||
:: Batch File Implementation |
|||
@echo off |
|||
setlocal enabledelayedexpansion |
|||
:: initialization |
|||
:begin |
|||
set "list_chars=123456789" |
|||
set "list_length=9" |
|||
set "code=" |
|||
set "code_length=4" %== this should be less than 10 ==% |
|||
set "tries=0" %== number of tries ==% |
|||
:: generate the code to be guessed by player |
|||
set "chars_left=%list_chars%" |
|||
for /l %%c in (1, 1, %code_length%) do ( |
|||
set /a "rnd=!random! %% (%list_length% + 1 - %%c)" |
|||
for %%? in (!rnd!) do set "pick_char=!chars_left:~%%?,1!" |
|||
set "code=!code!!pick_char!" |
|||
for %%? in (!pick_char!) do set "chars_left=!chars_left:%%?=!" |
|||
) |
|||
:: get the min and max allowable guess for input validation |
|||
set "min=!list_chars:~0,%code_length%!" |
|||
set "max=" |
|||
for /l %%c in (1, 1, %code_length%) do set "max=!max!!list_chars:~-%%c,1!" |
|||
:: display game |
|||
:display |
|||
cls |
|||
echo( |
|||
echo(Bulls and Cows Game |
|||
echo(Batch File Implementation |
|||
echo( |
|||
echo(Gameplay: |
|||
echo( |
|||
echo(I have generated a %code_length%-digit code from digits 1-9 without duplication. |
|||
echo(Your objective is to guess it. If your guess is equal to my code, |
|||
echo(then you WIN. If not, I will score your guess: |
|||
echo( |
|||
echo(** A score of one BULL is accumulated for each digit in your guess |
|||
echo(that equals the corresponding digit in my code. |
|||
echo( |
|||
echo(** A score of one COW is accumulated for each digit in your guess |
|||
echo(that also appears in my code, but in the WRONG position. |
|||
echo( |
|||
echo(Now, start guessing^^! |
|||
:: input guess |
|||
:guess |
|||
echo( |
|||
set "guess=" %== clear input ==% |
|||
set /p "guess=Your Guess: " |
|||
:: validate input |
|||
if "!guess!" gtr "%max%" goto invalid |
|||
if "!guess!" lss "%min%" goto invalid |
|||
set /a "last_idx=%code_length% - 1" |
|||
for /l %%i in (0, 1, %last_idx%) do ( |
|||
set /a "next_idx=%%i + 1" |
|||
for /l %%j in (!next_idx!, 1, %last_idx%) do ( |
|||
if "!guess:~%%i,1!" equ "!guess:~%%j,1!" goto invalid |
|||
) |
|||
) |
|||
goto score |
|||
:: display that input is invalid |
|||
:invalid |
|||
echo(Please input a valid guess. |
|||
goto guess |
|||
:: scoring section |
|||
:score |
|||
set /a "tries+=1" |
|||
if "%guess%" equ "%code%" goto win |
|||
set "cow=0" |
|||
set "bull=0" |
|||
for /l %%i in (0, 1, %last_idx%) do ( |
|||
for /l %%j in (0, 1, %last_idx%) do ( |
|||
if "!guess:~%%i,1!" equ "!code:~%%j,1!" ( |
|||
if "%%i" equ "%%j" ( |
|||
set /a "bull+=1" |
|||
) else ( |
|||
set /a "cow+=1" |
|||
) |
|||
) |
|||
) |
|||
) |
|||
:: display score and go back to user input |
|||
echo(BULLS = %bull%; COWS = %cow%. |
|||
goto guess |
|||
:: player wins! |
|||
:win |
|||
echo( |
|||
echo(After %tries% tries, YOU CRACKED IT^^! My code is %code%. |
|||
echo( |
|||
set /p "opt=Play again? " |
|||
if /i "!opt!" equ "y" goto begin |
|||
exit /b 0</syntaxhighlight> |
|||
{{Out}} |
|||
<pre> |
|||
Bulls and Cows Game |
|||
Batch File Implementation |
|||
Gameplay: |
|||
I have generated a 4-digit code from digits 1-9 without duplication. |
|||
Your objective is to guess it. If your guess is equal to my code, |
|||
then you WIN. If not, I will score your guess: |
|||
** A score of one BULL is accumulated for each digit in your guess |
|||
that equals the corresponding digit in my code. |
|||
** A score of one COW is accumulated for each digit in your guess |
|||
that also appears in my code, but in the WRONG position. |
|||
Now, start guessing! |
|||
Your Guess: 0123 |
|||
Please input a valid guess. |
|||
Your Guess: 1234 |
|||
BULLS = 0; COWS = 3. |
|||
Your Guess: 4123 |
|||
BULLS = 2; COWS = 1. |
|||
... |
|||
Your Guess: 4391 |
|||
BULLS = 2; COWS = 0. |
|||
Your Guess: 4521 |
|||
BULLS = 3; COWS = 0. |
|||
Your Guess: 4621 |
|||
BULLS = 3; COWS = 0. |
|||
Your Guess: 4821 |
|||
After 10 tries, YOU CRACKED IT! My code is 4821. |
|||
Play again? </pre> |
|||
=={{header|BBC BASIC}}== |
|||
<syntaxhighlight lang="bbcbasic"> secret$ = "" |
|||
REPEAT |
|||
c$ = CHR$(&30 + RND(9)) |
|||
IF INSTR(secret$, c$) = 0 secret$ += c$ |
|||
UNTIL LEN(secret$) = 4 |
|||
PRINT "Guess a four-digit number with no digit used twice."' |
|||
guesses% = 0 |
|||
REPEAT |
|||
REPEAT |
|||
INPUT "Enter your guess: " guess$ |
|||
IF LEN(guess$) <> 4 PRINT "Must be a four-digit number" |
|||
UNTIL LEN(guess$) = 4 |
|||
guesses% += 1 |
|||
IF guess$ = secret$ PRINT "You won after "; guesses% " guesses!" : END |
|||
bulls% = 0 |
|||
cows% = 0 |
|||
FOR i% = 1 TO 4 |
|||
c$ = MID$(secret$, i%, 1) |
|||
IF MID$(guess$, i%, 1) = c$ THEN |
|||
bulls% += 1 |
|||
ELSE IF INSTR(guess$, c$) THEN |
|||
cows% += 1 |
|||
ENDIF |
|||
ENDIF |
|||
NEXT i% |
|||
PRINT "You got " ;bulls% " bull(s) and " ;cows% " cow(s)." |
|||
UNTIL FALSE |
|||
</syntaxhighlight> |
|||
=={{header|BCPL}}== |
|||
<syntaxhighlight lang="bcpl">get "libhdr" |
|||
static $( randstate = ? $) |
|||
let randdigit() = valof |
|||
$( let x = ? |
|||
$( randstate := random(randstate) |
|||
x := (randstate >> 7) & 15 |
|||
$) repeatuntil 0 < x <= 9 |
|||
resultis x |
|||
$) |
|||
let gensecret(s) be |
|||
for i=0 to 3 |
|||
s!i := randdigit() repeatuntil valof |
|||
$( for j=0 to i-1 if s!i = s!j then resultis false |
|||
resultis true |
|||
$) |
|||
let bulls(secret, guess) = valof |
|||
$( let x = 0 |
|||
for i=0 to 3 if secret!i = guess!i then x := x + 1 |
|||
resultis x |
|||
$) |
|||
let cows(secret, guess) = valof |
|||
$( let x = 0 |
|||
for i=0 to 3 |
|||
for j=0 to 3 |
|||
unless i=j |
|||
if secret!i = guess!j then x := x + 1 |
|||
resultis x |
|||
$) |
|||
let readguess(guess) be |
|||
$( let g, v = ?, true |
|||
writes("Enter a guess, or 0 to quit: ") |
|||
g := readn() |
|||
if g=0 then finish |
|||
for i=3 to 0 by -1 |
|||
$( guess!i := g rem 10 |
|||
g := g / 10 |
|||
$) |
|||
for i=0 to 2 for j = i+1 to 3 |
|||
v := v & guess!i ~= 0 & guess!j ~= 0 & guess!i ~= guess!j |
|||
if v then return |
|||
writes("Invalid guess.*N") |
|||
$) repeat |
|||
let play(secret) be |
|||
$( let tries, b, c = 0, ?, ? |
|||
let guess = vec 3 |
|||
$( readguess(guess) |
|||
b := bulls(secret, guess) |
|||
c := cows(secret, guess) |
|||
writef("Bulls: %N, cows: %N*N", b, c); |
|||
tries := tries + 1 |
|||
$) repeatuntil b = 4 |
|||
writef("You win in %N tries.*N", tries) |
|||
$) |
|||
let start() be |
|||
$( let secret = vec 3 |
|||
writes("Bulls and cows*N----- --- ----*N") |
|||
writes("Please enter a random seed: ") |
|||
randstate := readn() |
|||
wrch('*N') |
|||
gensecret(secret) |
|||
play(secret) |
|||
$)</syntaxhighlight> |
|||
{{out}} |
|||
<pre>Bulls and cows |
|||
----- --- ---- |
|||
Please enter a random seed: 20394 |
|||
Enter a guess, or 0 to quit: 1234 |
|||
Bulls: 0, cows: 3 |
|||
Enter a guess, or 0 to quit: 4321 |
|||
Bulls: 1, cows: 2 |
|||
Enter a guess, or 0 to quit: 1423 |
|||
Bulls: 2, cows: 1 |
|||
Enter a guess, or 0 to quit: 1243 |
|||
Bulls: 1, cows: 2 |
|||
Enter a guess, or 0 to quit: 4123 |
|||
Bulls: 3, cows: 0 |
|||
Enter a guess, or 0 to quit: 4523 |
|||
Bulls: 2, cows: 0 |
|||
Enter a guess, or 0 to quit: 5123 |
|||
Bulls: 3, cows: 0 |
|||
Enter a guess, or 0 to quit: 6123 |
|||
Bulls: 3, cows: 0 |
|||
Enter a guess, or 0 to quit: 7123 |
|||
Bulls: 4, cows: 0 |
|||
You win in 9 tries.</pre> |
|||
=={{header|Brat}}== |
|||
<syntaxhighlight lang="brat">secret_length = 4 |
|||
secret = [1 2 3 4 5 6 7 8 9].shuffle.pop secret_length |
|||
score = { guess | |
|||
cows = 0 |
|||
bulls = 0 |
|||
guess.each_with_index { digit, index | |
|||
true? digit == secret[index] |
|||
{ bulls = bulls + 1 } |
|||
{ true? secret.include?(digit) |
|||
{ cows = cows + 1 } |
|||
} |
|||
} |
|||
[cows: cows, bulls: bulls] |
|||
} |
|||
won = false |
|||
guesses = 1 |
|||
p "I have chosen a number with four unique digits from 1 through 9. Can you guess it?" |
|||
while { not won } |
|||
{ |
|||
print "Guess #{guesses}: " |
|||
guess = g.strip.dice.map { d | d.to_i } |
|||
when { guess == secret } { p "You won in #{guesses} guesses!"; won = true } |
|||
{ guess.include?(0) || guess.include?(null) } { p "Your guess should only include digits 1 through 9." } |
|||
{ guess.length != secret.length } { p "Your guess was not the correct length. The number has exactly #{secret.length} digits." } |
|||
{ guess.unique.length != secret.length } { p "Each digit should only appear once in your guess." } |
|||
{ true } { |
|||
result = score guess |
|||
p "Score: #{result[:bulls]} bulls, #{result[:cows]} cows." |
|||
guesses = guesses + 1 |
|||
} |
|||
}</syntaxhighlight> |
|||
=={{header|C}}== |
=={{header|C}}== |
||
{{libheader|ncurses}} |
{{libheader|ncurses}} |
||
< |
<syntaxhighlight lang="c">#include <stdio.h> |
||
#include <stdarg.h> |
#include <stdarg.h> |
||
#include <stdlib.h> |
#include <stdlib.h> |
||
Line 264: | Line 1,336: | ||
} |
} |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
The following function contains the code to check how many bulls and cows there are. |
The following function contains the code to check how many bulls and cows there are. |
||
< |
<syntaxhighlight lang="c">bool take_it_or_not() |
||
{ |
{ |
||
int i; |
int i; |
||
Line 352: | Line 1,424: | ||
nocbreak(); echo(); endwin(); |
nocbreak(); echo(); endwin(); |
||
return EXIT_SUCCESS; |
return EXIT_SUCCESS; |
||
}</ |
}</syntaxhighlight> |
||
=={{header|C sharp|C#}}== |
|||
<syntaxhighlight lang="csharp">using System; |
|||
namespace BullsnCows |
|||
{ |
|||
class Program |
|||
{ |
|||
static void Main(string[] args) |
|||
{ |
|||
int[] nums = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; |
|||
KnuthShuffle<int>(ref nums); |
|||
int[] chosenNum = new int[4]; |
|||
Array.Copy(nums, chosenNum, 4); |
|||
Console.WriteLine("Your Guess ?"); |
|||
while (!game(Console.ReadLine(), chosenNum)) |
|||
{ |
|||
Console.WriteLine("Your next Guess ?"); |
|||
} |
|||
Console.ReadKey(); |
|||
} |
|||
public static void KnuthShuffle<T>(ref T[] array) |
|||
{ |
|||
System.Random random = new System.Random(); |
|||
for (int i = 0; i < array.Length; i++) |
|||
{ |
|||
int j = random.Next(array.Length); |
|||
T temp = array[i]; array[i] = array[j]; array[j] = temp; |
|||
} |
|||
} |
|||
public static bool game(string guess, int[] num) |
|||
{ |
|||
char[] guessed = guess.ToCharArray(); |
|||
int bullsCount = 0, cowsCount = 0; |
|||
if (guessed.Length != 4) |
|||
{ |
|||
Console.WriteLine("Not a valid guess."); |
|||
return false; |
|||
} |
|||
for (int i = 0; i < 4; i++) |
|||
{ |
|||
int curguess = (int) char.GetNumericValue(guessed[i]); |
|||
if (curguess < 1 || curguess > 9) |
|||
{ |
|||
Console.WriteLine("Digit must be ge greater 0 and lower 10."); |
|||
return false; |
|||
} |
|||
if (curguess == num[i]) |
|||
{ |
|||
bullsCount++; |
|||
} |
|||
else |
|||
{ |
|||
for (int j = 0; j < 4; j++) |
|||
{ |
|||
if (curguess == num[j]) |
|||
cowsCount++; |
|||
} |
|||
} |
|||
} |
|||
if (bullsCount == 4) |
|||
{ |
|||
Console.WriteLine("Congratulations! You have won!"); |
|||
return true; |
|||
} |
|||
else |
|||
{ |
|||
Console.WriteLine("Your Score is {0} bulls and {1} cows", bullsCount, cowsCount); |
|||
return false; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
</syntaxhighlight> |
|||
=={{header|C++}}== |
=={{header|C++}}== |
||
<syntaxhighlight lang="cpp">#include <iostream> |
|||
<lang cpp> |
|||
#include <iostream> |
|||
#include <string> |
#include <string> |
||
#include <algorithm> |
#include <algorithm> |
||
Line 372: | Line 1,523: | ||
std::string symbols = "0123456789"; |
std::string symbols = "0123456789"; |
||
int const selection_length = 4; |
unsigned int const selection_length = 4; |
||
std::random_shuffle(symbols.begin(), symbols.end()); |
std::random_shuffle(symbols.begin(), symbols.end()); |
||
Line 381: | Line 1,532: | ||
if (guess.length() != selection_length |
if (guess.length() != selection_length |
||
|| guess.find_first_not_of(symbols) != std::string::npos |
|| guess.find_first_not_of(symbols) != std::string::npos |
||
|| contains_duplicates( |
|| contains_duplicates(guess)) |
||
{ |
{ |
||
std::cout << guess << " is not a valid guess!"; |
std::cout << guess << " is not a valid guess!"; |
||
Line 387: | Line 1,538: | ||
} |
} |
||
int bulls = 0; |
unsigned int bulls = 0; |
||
int cows = 0; |
unsigned int cows = 0; |
||
for (index i = 0; i != selection_length; ++i) |
for (index i = 0; i != selection_length; ++i) |
||
{ |
{ |
||
Line 401: | Line 1,552: | ||
{ |
{ |
||
std::cout << "Congratulations! You have won!\n"; |
std::cout << "Congratulations! You have won!\n"; |
||
return |
return; |
||
} |
} |
||
} |
} |
||
Line 433: | Line 1,584: | ||
std::cout << "Another game? "; |
std::cout << "Another game? "; |
||
} |
} |
||
}</syntaxhighlight> |
|||
=={{header|Ceylon}}== |
|||
<syntaxhighlight lang="ceylon">import ceylon.random { |
|||
DefaultRandom |
|||
} |
} |
||
</lang> |
|||
shared void run() { |
|||
=={{header|Common Lisp}}== |
|||
value random = DefaultRandom(); |
|||
<lang lisp>(defun get-number () |
|||
function generateDigits() => |
|||
random.elements(1..9).distinct.take(4).sequence(); |
|||
function validate(String guess) { |
|||
variable value ok = true; |
|||
if (!guess.every((Character element) => element.digit)) { |
|||
print("numbers only, please"); |
|||
ok = false; |
|||
} |
|||
if ('0' in guess) { |
|||
print("only 1 to 9, please"); |
|||
ok = false; |
|||
} |
|||
if (guess.distinct.shorterThan(guess.size)) { |
|||
print("no duplicates, please"); |
|||
ok = false; |
|||
} |
|||
if (guess.size != 4) { |
|||
print("4 digits please"); |
|||
ok = false; |
|||
} |
|||
return ok; |
|||
} |
|||
function score({Integer*} target, {Integer*} guess) { |
|||
variable value bulls = 0; |
|||
variable value cows = 0; |
|||
for ([a, b] in zipPairs(target, guess)) { |
|||
if (a == b) { |
|||
bulls++; |
|||
} else if (target.contains(b)) { |
|||
cows++; |
|||
} |
|||
} |
|||
return [bulls, cows]; |
|||
} |
|||
while (true) { |
|||
value digits = generateDigits(); |
|||
print("I have chosen my four digits, please guess what they are. |
|||
Use only the digits 1 to 9 with no duplicates and enter them with no spaces. eg 1234 |
|||
Enter q or Q to quit."); |
|||
while (true) { |
|||
if (exists line = process.readLine()) { |
|||
if (line.uppercased == "Q") { |
|||
return; |
|||
} |
|||
if (validate(line)) { |
|||
value guessDigits = line.map((Character element) => Integer.parse(element.string)).narrow<Integer>(); |
|||
value [bulls, cows] = score(digits, guessDigits); |
|||
if (bulls == 4) { |
|||
print("You win!"); |
|||
break; |
|||
} |
|||
else { |
|||
print("Bulls: ``bulls``, Cows: ``cows``"); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
}</syntaxhighlight> |
|||
=={{header|Clojure}}== |
|||
<syntaxhighlight lang="clojure"> |
|||
(ns bulls-and-cows) |
|||
(defn bulls [guess solution] |
|||
(count (filter true? (map = guess solution)))) |
|||
(defn cows [guess solution] |
|||
(- |
|||
(count (filter (set solution) guess)) |
|||
(bulls guess solution))) |
|||
(defn valid-input? |
|||
"checks whether the string is a 4 digit number with unique digits" |
|||
[user-input] |
|||
(if (re-seq #"^(?!.*(\d).*\1)\d{4}$" user-input) |
|||
true |
|||
false)) |
|||
(defn enter-guess [] |
|||
"Let the user enter a guess. Verify the input. Repeat until valid. |
|||
returns a list of digits enters by the user (# # # #)" |
|||
(println "Enter your guess: ") |
|||
(let [guess (read-line)] |
|||
(if (valid-input? guess) |
|||
(map #(Character/digit % 10) guess) |
|||
(recur)))) |
|||
(defn bulls-and-cows [] |
|||
"generate a random 4 digit number from the list of (1 ... 9): no repeating digits |
|||
player tries to guess the number with bull and cows rules gameplay" |
|||
(let [solution ( take 4 (shuffle (range 1 10)))] |
|||
(println "lets play some bulls and cows!") |
|||
(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) |
|||
</syntaxhighlight> |
|||
=={{header|CLU}}== |
|||
<syntaxhighlight lang="clu">% This program needs to be merged with PCLU's "misc" library |
|||
% to use the random number generator. |
|||
% |
|||
% pclu -merge $CLUHOME/lib/misc.lib -compile bulls_cows.clu |
|||
% Seed the random number generator with the current time |
|||
init_rng = proc () |
|||
d: date := now() |
|||
seed: int := ((d.hour*60) + d.minute)*60 + d.second |
|||
random$seed(seed) |
|||
end init_rng |
|||
% Generate a secret |
|||
make_secret = proc () returns (sequence[int]) |
|||
secret: array[int] := array[int]$[0,0,0,0] |
|||
for i: int in int$from_to(1,4) do |
|||
digit: int |
|||
valid: bool := false |
|||
while ~valid do |
|||
digit := 1+random$next(9) |
|||
valid := true |
|||
for j: int in int$from_to(1, i-1) do |
|||
if secret[i] = digit then |
|||
valid := false |
|||
break |
|||
end |
|||
end |
|||
end |
|||
secret[i] := digit |
|||
end |
|||
return(sequence[int]$a2s(secret)) |
|||
end make_secret |
|||
% Count the bulls |
|||
bulls = proc (secret, input: sequence[int]) returns (int) |
|||
n_bulls: int := 0 |
|||
for i: int in int$from_to(1,4) do |
|||
if secret[i] = input[i] then n_bulls := n_bulls + 1 end |
|||
end |
|||
return(n_bulls) |
|||
end bulls |
|||
% Count the cows |
|||
cows = proc (secret, input: sequence[int]) returns (int) |
|||
n_cows: int := 0 |
|||
for i: int in int$from_to(1,4) do |
|||
for j: int in int$from_to(1,4) do |
|||
if i ~= j cand secret[i] = input[j] then |
|||
n_cows := n_cows + 1 |
|||
end |
|||
end |
|||
end |
|||
return(n_cows) |
|||
end cows |
|||
% Read a guess |
|||
player_guess = proc () returns (sequence[int]) |
|||
pi: stream := stream$primary_input() |
|||
po: stream := stream$primary_output() |
|||
while true do % we will keep reading until the guess is valid |
|||
stream$puts(po, "Guess? ") |
|||
guess: string := stream$getl(pi) |
|||
% check length |
|||
if string$size(guess) ~= 4 then |
|||
stream$putl(po, "Invalid guess: need four digits.") |
|||
continue |
|||
end |
|||
% get and check digits |
|||
valid: bool := true |
|||
digits: sequence[int] := sequence[int]$[] |
|||
for c: char in string$chars(guess) do |
|||
i: int := char$c2i(c) - 48 |
|||
if ~(i>=1 & i<=9) then |
|||
valid := false |
|||
break |
|||
end |
|||
digits := sequence[int]$addh(digits,i) |
|||
end |
|||
if ~valid then |
|||
stream$putl(po, "Invalid guess: each position needs to be a digit 1-9.") |
|||
continue |
|||
end |
|||
% check that there are no duplicates |
|||
valid := true |
|||
for i: int in int$from_to(1,4) do |
|||
for j: int in int$from_to(i+1,4) do |
|||
if digits[i] = digits[j] then |
|||
valid := false |
|||
break |
|||
end |
|||
end |
|||
end |
|||
if ~valid then |
|||
stream$putl(po, "Invalid guess: there must be no duplicate digits.") |
|||
continue |
|||
end |
|||
return(digits) |
|||
end |
|||
end player_guess |
|||
% Play a game |
|||
play_game = proc (secret: sequence[int]) |
|||
po: stream := stream$primary_output() |
|||
n_guesses: int := 0 |
|||
while true do |
|||
n_guesses := n_guesses + 1 |
|||
guess: sequence[int] := player_guess() |
|||
n_bulls: int := bulls(secret, guess) |
|||
n_cows: int := cows(secret, guess) |
|||
stream$putl(po, "Bulls: " || int$unparse(n_bulls) |
|||
|| ", cows: " || int$unparse(n_cows)) |
|||
if n_bulls = 4 then |
|||
stream$putl(po, "Congratulations! You won in " |
|||
|| int$unparse(n_guesses) || " tries.") |
|||
break |
|||
end |
|||
end |
|||
end play_game |
|||
start_up = proc () |
|||
po: stream := stream$primary_output() |
|||
init_rng() |
|||
stream$putl(po, "Bulls and cows\n----- --- ----\n") |
|||
play_game(make_secret()) |
|||
end start_up</syntaxhighlight> |
|||
{{out}} |
|||
<pre>Bulls and cows |
|||
----- --- ---- |
|||
Guess? 1234 |
|||
Bulls: 0, cows: 1 |
|||
Guess? 5678 |
|||
Bulls: 0, cows: 2 |
|||
Guess? 4579 |
|||
Bulls: 1, cows: 2 |
|||
Guess? 3579 |
|||
Bulls: 2, cows: 2 |
|||
Guess? 3759 |
|||
Bulls: 4, cows: 0 |
|||
Congratulations! You won in 5 tries.</pre> |
|||
=={{header|Coco}}== |
|||
{{libheader|Underscore.js}} |
|||
To handle I/O, we use functions named <code>say</code> (which simply outputs a string) and <code>prompt</code> (which takes a prompt string to display to the user and returns a line of input, without a trailing newline). These require platform-specific implementations. Here's how they can be implemented for the SpiderMonkey shell: |
|||
<syntaxhighlight lang="coco">say = print |
|||
prompt = (str) -> |
|||
putstr str |
|||
readline! ? quit!</syntaxhighlight> |
|||
We can now solve the task using <code>say</code> and <code>prompt</code>: |
|||
<syntaxhighlight lang="coco">const SIZE = 4 |
|||
secret = _.sample ['1' to '9'], SIZE |
|||
for ever |
|||
var guess |
|||
for ever |
|||
guess := _.uniq prompt 'Enter a guess: ' |
|||
if guess.length === SIZE and not _.difference guess, ['1' to '9'] .length |
|||
break |
|||
say 'Malformed guess; try again.' |
|||
bulls = cows = 0 |
|||
for i til SIZE |
|||
if guess[i] === secret[i] |
|||
++bulls |
|||
else if _.contains secret, guess[i] |
|||
++cows |
|||
if bulls === SIZE |
|||
break |
|||
say "#bulls bull#{[if bulls !== 1 then 's']}, #cows cow#{[if cows !== 1 then 's']}." |
|||
say 'A winner is you!'</syntaxhighlight> |
|||
=={{header|Common Lisp}}== |
|||
<syntaxhighlight lang="lisp">(defun get-number () |
|||
(do ((digits '())) |
(do ((digits '())) |
||
((>= (length digits) 4) digits) |
((>= (length digits) 4) digits) |
||
Line 479: | Line 1,922: | ||
(format stream "~&Correct, you win!") |
(format stream "~&Correct, you win!") |
||
(format stream "~&Score: ~a cows, ~a bulls." |
(format stream "~&Score: ~a cows, ~a bulls." |
||
cows bulls)))))))</ |
cows bulls)))))))</syntaxhighlight> |
||
=={{header|Crystal}}== |
|||
{{trans|Ruby}} |
|||
<syntaxhighlight lang="ruby">size = 4 |
|||
secret = ('1'..'9').to_a.sample(size) |
|||
guess = [] of Char |
|||
i = 0 |
|||
loop do |
|||
i += 1 |
|||
loop do |
|||
print "Guess #{i}: " |
|||
guess = gets.not_nil!.chomp.chars |
|||
exit if guess.empty? |
|||
break if guess.size == size && |
|||
guess.all? { |x| ('1'..'9').includes? x } && |
|||
guess.uniq.size == size |
|||
puts "Problem, try again. You need to enter #{size} unique digits from 1 to 9" |
|||
end |
|||
if guess == secret |
|||
puts "Congratulations you guessed correctly in #{i} attempts" |
|||
break |
|||
end |
|||
bulls = cows = 0 |
|||
size.times do |j| |
|||
if guess[j] == secret[j] |
|||
bulls += 1 |
|||
elsif secret.includes? guess[j] |
|||
cows += 1 |
|||
end |
|||
end |
|||
puts "Bulls: #{bulls}; Cows: #{cows}" |
|||
end</syntaxhighlight> |
|||
=={{header|D}}== |
|||
<syntaxhighlight lang="d">void main() { |
|||
import std.stdio, std.random, std.string, std.algorithm, |
|||
std.range, std.ascii; |
|||
immutable hidden = "123456789"d.randomCover.take(4).array; |
|||
while (true) { |
|||
"Next guess: ".write; |
|||
const d = readln.strip.array.sort().release; |
|||
if (d.count == 4 && d.all!isDigit && d.uniq.count == 4) { |
|||
immutable bulls = d.zip(hidden).count!q{ a[0] == a[1] }, |
|||
cows = d.count!(g => hidden.canFind(g)) - bulls; |
|||
if (bulls == 4) |
|||
return " You guessed it!".writeln; |
|||
writefln("bulls %d, cows %d", bulls, cows); |
|||
} |
|||
" Bad guess! (4 unique digits, 1-9)".writeln; |
|||
} |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
<pre>Next guess: 6548 |
|||
bulls 0, cows 3 |
|||
Bad guess! (4 unique digits, 1-9) |
|||
Next guess: 5284 |
|||
bulls 2, cows 1 |
|||
Bad guess! (4 unique digits, 1-9) |
|||
Next guess: 4386 |
|||
bulls 0, cows 2 |
|||
Bad guess! (4 unique digits, 1-9) |
|||
Next guess: - |
|||
Bad guess! (4 unique digits, 1-9) |
|||
Next guess: 5894 |
|||
bulls 3, cows 0 |
|||
Bad guess! (4 unique digits, 1-9) |
|||
Next guess: 5874 |
|||
bulls 3, cows 0 |
|||
Bad guess! (4 unique digits, 1-9) |
|||
Next guess: 5814 |
|||
You guessed it!</pre> |
|||
=={{header|Delphi}}== |
|||
See [[#Pascal]]. |
|||
=={{header|Draco}}== |
|||
<syntaxhighlight lang="draco">union { |
|||
ulong state; |
|||
struct { |
|||
byte x; |
|||
byte a; |
|||
byte b; |
|||
byte c; |
|||
} fields; |
|||
} rng; |
|||
proc rand() byte: |
|||
rng.fields.x := rng.fields.x + 1; |
|||
rng.fields.a := rng.fields.a >< rng.fields.c >< rng.fields.x; |
|||
rng.fields.b := rng.fields.b + rng.fields.a; |
|||
rng.fields.c := rng.fields.c + (rng.fields.b >> 1) >< rng.fields.a; |
|||
rng.fields.c |
|||
corp |
|||
proc rand_digit() byte: |
|||
byte digit; |
|||
while |
|||
digit := rand() & 15; |
|||
digit < 1 or digit >= 10 |
|||
do od; |
|||
digit |
|||
corp |
|||
proc make_secret([4]byte secret) void: |
|||
int i, j; |
|||
bool ok; |
|||
for i from 0 upto 3 do |
|||
while |
|||
secret[i] := rand_digit(); |
|||
ok := true; |
|||
for j from 0 upto i-1 do |
|||
ok := ok and secret[i] /= secret[j] |
|||
od; |
|||
not ok |
|||
do od |
|||
od |
|||
corp |
|||
proc bulls([4]byte secret, guess) byte: |
|||
byte i, count; |
|||
count := 0; |
|||
for i from 0 upto 3 do |
|||
if secret[i] = guess[i] then count := count + 1 fi |
|||
od; |
|||
count |
|||
corp |
|||
proc cows([4]byte secret, guess) byte: |
|||
byte i, j, count; |
|||
count := 0; |
|||
for i from 0 upto 3 do |
|||
for j from 0 upto 3 do |
|||
if i /= j and secret[i] = guess[j] then count := count + 1 fi |
|||
od |
|||
od; |
|||
count |
|||
corp |
|||
proc read_guess([4]byte guess) void: |
|||
word guessNo; |
|||
byte i; |
|||
while |
|||
write("Guess? "); |
|||
readln(guessNo); |
|||
if guessNo<1111 or guessNo>9999 then true |
|||
else |
|||
for i from 3 downto 0 do |
|||
guess[i] := guessNo % 10; |
|||
guessNo := guessNo / 10; |
|||
od; |
|||
guess[0]*guess[1]*guess[2]*guess[3] = 0 |
|||
fi |
|||
do |
|||
writeln("A guess must be a four-digit number not containing zeroes.") |
|||
od |
|||
corp |
|||
proc play_game([4]byte secret) word: |
|||
[4]byte guess; |
|||
word tries; |
|||
tries := 1; |
|||
while |
|||
read_guess(guess); |
|||
writeln("Bulls: ", bulls(secret, guess), ", cows: ", cows(secret, guess)); |
|||
bulls(secret, guess) /= 4 |
|||
do |
|||
tries := tries + 1 |
|||
od; |
|||
tries |
|||
corp |
|||
proc main() void: |
|||
[4]byte secret; |
|||
word tries; |
|||
write("Please enter a random seed: "); |
|||
readln(rng.state); |
|||
make_secret(secret); |
|||
tries := play_game(secret); |
|||
writeln(); |
|||
writeln("You got it in ", tries, " tries.") |
|||
corp</syntaxhighlight> |
|||
{{out}} |
|||
<pre>Please enter a random seed: 123456 |
|||
Guess? 1234 |
|||
Bulls: 2, cows: 1 |
|||
Guess? 5678 |
|||
Bulls: 0, cows: 0 |
|||
Guess? 9234 |
|||
Bulls: 1, cows: 2 |
|||
Guess? 1934 |
|||
Bulls: 3, cows: 0 |
|||
Guess? 1294 |
|||
Bulls: 2, cows: 2 |
|||
Guess? 1924 |
|||
Bulls: 4, cows: 0 |
|||
You got it in 6 tries.</pre> |
|||
=={{header|E}}== |
=={{header|E}}== |
||
Line 485: | Line 2,131: | ||
Note: This example was deliberately written in an abstracted style, separating out the algorithms, game logic, and UI. |
Note: This example was deliberately written in an abstracted style, separating out the algorithms, game logic, and UI. |
||
< |
<syntaxhighlight lang="e">def Digit := 1..9 |
||
def Number := Tuple[Digit,Digit,Digit,Digit] |
def Number := Tuple[Digit,Digit,Digit,Digit] |
||
Line 566: | Line 2,212: | ||
return gameTurn() |
return gameTurn() |
||
}</ |
}</syntaxhighlight> |
||
===REPL user interface=== |
===REPL user interface=== |
||
Line 588: | Line 2,234: | ||
{{works with|E-on-Java}} (Java Swing) |
{{works with|E-on-Java}} (Java Swing) |
||
< |
<syntaxhighlight lang="e">def guiBullsAndCows() { |
||
var lastGuess := "" |
var lastGuess := "" |
||
def op := <unsafe:javax.swing.makeJOptionPane> |
def op := <unsafe:javax.swing.makeJOptionPane> |
||
Line 602: | Line 2,248: | ||
op.showMessageDialog(null, msg) |
op.showMessageDialog(null, msg) |
||
}, entropy) |
}, entropy) |
||
}</ |
}</syntaxhighlight> |
||
=={{header|EasyLang}}== |
|||
<syntaxhighlight> |
|||
dig[] = [ 1 2 3 4 5 6 7 8 9 ] |
|||
for i = 1 to 4 |
|||
h = i - 1 + random (10 - i) |
|||
swap dig[i] dig[h] |
|||
. |
|||
# print dig[] |
|||
len g[] 4 |
|||
attempts = 0 |
|||
repeat |
|||
repeat |
|||
ok = 0 |
|||
s$[] = strchars input |
|||
if len s$[] = 4 |
|||
ok = 1 |
|||
for i = 1 to 4 |
|||
g[i] = number s$[i] |
|||
if g[i] = 0 |
|||
ok = 0 |
|||
. |
|||
. |
|||
. |
|||
until ok = 1 |
|||
. |
|||
print g[] |
|||
attempts += 1 |
|||
bulls = 0 |
|||
cows = 0 |
|||
for i = 1 to 4 |
|||
if g[i] = dig[i] |
|||
bulls += 1 |
|||
else |
|||
for j = 1 to 4 |
|||
if dig[j] = g[i] |
|||
cows += 1 |
|||
. |
|||
. |
|||
. |
|||
. |
|||
print "bulls:" & bulls & " cows:" & cows |
|||
until bulls = 4 |
|||
. |
|||
print "Well done! " & attempts & " attempts needed." |
|||
</syntaxhighlight> |
|||
=={{header|Eiffel}}== |
|||
<syntaxhighlight lang="eiffel"> |
|||
class |
|||
BULLS_AND_COWS |
|||
create |
|||
execute |
|||
feature |
|||
execute |
|||
-- Initiate game. |
|||
do |
|||
io.put_string ("Let's play bulls and cows.%N") |
|||
create answer.make_empty |
|||
play |
|||
end |
|||
feature {NONE} |
|||
play |
|||
-- Plays bulls ans cows. |
|||
local |
|||
count, seed: INTEGER |
|||
guess: STRING |
|||
do |
|||
from |
|||
until |
|||
seed > 0 |
|||
loop |
|||
io.put_string ("Enter a positive integer.%NYour play will be generated from it.%N") |
|||
io.read_integer |
|||
seed := io.last_integer |
|||
end |
|||
generate_answer (seed) |
|||
io.put_string ("Your game has been created.%N Try to guess the four digit number.%N") |
|||
create guess.make_empty |
|||
from |
|||
until |
|||
guess ~ answer |
|||
loop |
|||
io.put_string ("Guess: ") |
|||
io.read_line |
|||
guess := io.last_string |
|||
if guess.count = 4 and guess.is_natural and not guess.has ('0') then |
|||
io.put_string (score (guess) + "%N") |
|||
count := count + 1 |
|||
else |
|||
io.put_string ("Your input does not have the correct format.") |
|||
end |
|||
end |
|||
io.put_string ("Congratulations! You won with " + count.out + " guesses.") |
|||
end |
|||
answer: STRING |
|||
generate_answer (s: INTEGER) |
|||
-- Answer with 4-digits between 1 and 9 stored in 'answer'. |
|||
require |
|||
positive_seed: s > 0 |
|||
local |
|||
random: RANDOM |
|||
ran: INTEGER |
|||
do |
|||
create random.set_seed (s) |
|||
from |
|||
until |
|||
answer.count = 4 |
|||
loop |
|||
ran := (random.double_item * 10).floor |
|||
if ran > 0 and not answer.has_substring (ran.out) then |
|||
answer.append (ran.out) |
|||
end |
|||
random.forth |
|||
end |
|||
ensure |
|||
answer_not_void: answer /= Void |
|||
correct_length: answer.count = 4 |
|||
end |
|||
score (g: STRING): STRING |
|||
-- Score for the guess 'g' depending on 'answer'. |
|||
require |
|||
same_length: answer.count = g.count |
|||
local |
|||
k: INTEGER |
|||
a, ge: STRING |
|||
do |
|||
Result := "" |
|||
a := answer.twin |
|||
ge := g.twin |
|||
across |
|||
1 |..| a.count as c |
|||
loop |
|||
if a [c.item] ~ ge [c.item] then |
|||
Result := Result + "BULL " |
|||
a [c.item] := ' ' |
|||
ge [c.item] := ' ' |
|||
end |
|||
end |
|||
across |
|||
1 |..| a.count as c |
|||
loop |
|||
if a [c.item] /= ' ' then |
|||
k := ge.index_of (a [c.item], 1) |
|||
if k > 0 then |
|||
Result := Result + "COW " |
|||
ge [k] := ' ' |
|||
end |
|||
end |
|||
end |
|||
end |
|||
end |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Let's play bulls and cows. |
|||
Enter a positive integer. |
|||
Your play will be generated from it. |
|||
2 |
|||
Guess: 2497 |
|||
BULL COW |
|||
Guess: 2486 |
|||
BULL COW COW |
|||
Guess: 2485 |
|||
BULL COW COW |
|||
Guess: 2483 |
|||
BULL BULL COW COW |
|||
Guess: 2438 |
|||
BULL COW COW COW |
|||
Guess: 2843 |
|||
BULL BULL BULL BULL |
|||
Congratulations! You won with 6 guesses. |
|||
</pre> |
|||
=={{header|Elena}}== |
|||
ELENA 6.x : |
|||
<syntaxhighlight lang="elena">import system'routines; |
|||
import extensions; |
|||
class GameMaster |
|||
{ |
|||
field _numbers; |
|||
field _attempt; |
|||
constructor() |
|||
{ |
|||
// generate secret number |
|||
var randomNumbers := new int[]{1,2,3,4,5,6,7,8,9}.randomize(9); |
|||
_numbers := randomNumbers.Subarray(0, 4); |
|||
_attempt := new Integer(1); |
|||
} |
|||
ask() |
|||
{ |
|||
var row := console.print("Your Guess #",_attempt," ?").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 == _numbers[i]) |
|||
{ |
|||
bulls += 1 |
|||
} |
|||
else |
|||
{ |
|||
if (_numbers.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 } |
|||
! { |
|||
_attempt.append(1); |
|||
console.printLine("Your Score is ",bulls," bulls and ",cows," cows"); |
|||
^ true |
|||
} |
|||
} |
|||
} |
|||
public program() |
|||
{ |
|||
var gameMaster := new GameMaster(); |
|||
var process := $lazy gameMaster.proceed(gameMaster.ask()); |
|||
process.doWhile(); |
|||
console.readChar() |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Your Guess #1 ?2497 |
|||
Your Score is 1 bulls and 1 cows |
|||
Your Guess #2 ?2486 |
|||
Your Score is 1 bulls and 2 cows |
|||
Your Guess #3 ?2485 |
|||
Your Score is 1 bulls and 2 cows |
|||
Your Guess #4 ?2483 |
|||
Your Score is 2 bulls and 2 cows |
|||
Your Guess #5 ?2438 |
|||
Your Score is 1 bulls and 3 cows |
|||
Your Guess #6 ?2843 |
|||
Congratulations! You have won! |
|||
</pre> |
|||
=={{header|Elixir}}== |
|||
{{works with|Elixir|1.2}} |
|||
<syntaxhighlight lang="elixir">defmodule Bulls_and_cows do |
|||
def play(size \\ 4) do |
|||
secret = Enum.take_random(1..9, size) |> Enum.map(&to_string/1) |
|||
play(size, secret) |
|||
end |
|||
defp play(size, secret) do |
|||
guess = input(size) |
|||
if guess == secret do |
|||
IO.puts "You win!" |
|||
else |
|||
{bulls, cows} = count(guess, secret) |
|||
IO.puts " Bulls: #{bulls}; Cows: #{cows}" |
|||
play(size, secret) |
|||
end |
|||
end |
|||
defp input(size) do |
|||
guess = IO.gets("Enter your #{size}-digit guess: ") |> String.strip |
|||
cond do |
|||
guess == "" -> |
|||
IO.puts "Give up" |
|||
exit(:normal) |
|||
String.length(guess)==size and String.match?(guess, ~r/^[1-9]+$/) -> |
|||
String.codepoints(guess) |
|||
true -> input(size) |
|||
end |
|||
end |
|||
defp count(guess, secret) do |
|||
Enum.zip(guess, secret) |> |
|||
Enum.reduce({0,0}, fn {g,s},{bulls,cows} -> |
|||
cond do |
|||
g == s -> {bulls + 1, cows} |
|||
g in secret -> {bulls, cows + 1} |
|||
true -> {bulls, cows} |
|||
end |
|||
end) |
|||
end |
|||
end |
|||
Bulls_and_cows.play</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Enter your 4-digit guess: 1234 |
|||
Bulls: 1; Cows: 1 |
|||
Enter your 4-digit guess: 5678 |
|||
Bulls: 0; Cows: 2 |
|||
Enter your 4-digit guess: 2345 |
|||
Bulls: 0; Cows: 1 |
|||
Enter your 4-digit guess: 1456 |
|||
Bulls: 1; Cows: 0 |
|||
Enter your 4-digit guess: 1782 |
|||
You win! |
|||
</pre> |
|||
=={{header|Erlang}}== |
|||
Module: |
|||
<syntaxhighlight lang="erlang">-module(bulls_and_cows). |
|||
-export([generate_secret/0, score_guess/2, play/0]). |
|||
% generate the secret code |
|||
generate_secret() -> generate_secret([], 4, lists:seq(1,9)). |
|||
generate_secret(Secret, 0, _) -> Secret; |
|||
generate_secret(Secret, N, Digits) -> |
|||
Next = lists:nth(random:uniform(length(Digits)), Digits), |
|||
generate_secret(Secret ++ [Next], N - 1, Digits -- [Next]). |
|||
% evaluate a guess |
|||
score_guess(Secret, Guess) |
|||
when length(Secret) =/= length(Guess) -> throw(badguess); |
|||
score_guess(Secret, Guess) -> |
|||
Bulls = count_bulls(Secret,Guess), |
|||
Cows = count_cows(Secret, Guess, Bulls), |
|||
[Bulls, Cows]. |
|||
% count bulls (exact matches) |
|||
count_bulls(Secret, Guess) -> |
|||
length(lists:filter(fun(I) -> lists:nth(I,Secret) == lists:nth(I,Guess) end, |
|||
lists:seq(1, length(Secret)))). |
|||
% count cows (digits present but out of place) |
|||
count_cows(Secret, Guess, Bulls) -> |
|||
length(lists:filter(fun(I) -> lists:member(I, Guess) end, Secret)) - Bulls. |
|||
% play a game |
|||
play() -> play_round(generate_secret()). |
|||
play_round(Secret) -> play_round(Secret, read_guess()). |
|||
play_round(Secret, Guess) -> |
|||
play_round(Secret, Guess, score_guess(Secret,Guess)). |
|||
play_round(_, _, [4,0]) -> |
|||
io:put_chars("Correct!\n"); |
|||
play_round(Secret, _, Score) -> |
|||
io:put_chars("\tbulls:"), io:write(hd(Score)), io:put_chars(", cows:"), |
|||
io:write(hd(tl(Score))), io:put_chars("\n"), play_round(Secret). |
|||
read_guess() -> |
|||
lists:map(fun(D)->D-48 end, |
|||
lists:sublist(io:get_line("Enter your 4-digit guess: "), 4)).</syntaxhighlight> |
|||
Script: |
|||
<syntaxhighlight lang="erlang">#!/usr/bin/escript |
|||
% Play Bulls and Cows |
|||
main(_) -> random:seed(now()), bulls_and_cows:play().</syntaxhighlight> |
|||
Sample play:<pre>Enter your 4-digit guess: 8376 |
|||
bulls:1, cows:0 |
|||
Enter your 4-digit guess: 8941 |
|||
bulls:1, cows:1 |
|||
Enter your 4-digit guess: 8529 |
|||
bulls:1, cows:1 |
|||
Enter your 4-digit guess: 4926 |
|||
bulls:1, cows:1 |
|||
Enter your 4-digit guess: 9321 |
|||
Correct! |
|||
</pre> |
|||
=={{header|Euphoria}}== |
|||
{{works with|Euphoria|4.0.3, 4.0.0 RC1 and later}} |
|||
<syntaxhighlight lang="euphoria">include std\text.e |
|||
include std\os.e |
|||
include std\sequence.e |
|||
include std\console.e |
|||
sequence bcData = {0,0} --bull,cow score for the player |
|||
sequence goalNum = { {0,0,0,0}, {0,0,0,0}, 0} --computer's secret number digits (element 1), marked as bull/cow |
|||
--indexes in element 2, integer value of it in element 3 |
|||
sequence currentGuess = { {0,0,0,0}, {0,0,0,0}, 0} --player's guess, same format as goalNum |
|||
sequence removeChars = 0 & " 0\r\t\n" --characters to trim (remove) from user's input. \r, \t are single escaped characters, |
|||
--0 is ascii 0x0 and number zero is ascii 48, or 0x30. The rest are wysiwyg |
|||
integer tries = 0 --track number of tries to guess the number |
|||
sequence bcStrings ={"bull", "cow"} --stores singular and/or plural strings depending on score in bcData |
|||
goalNum[1] = rand( {9,9,9,9} ) --rand function works on objects. here it outputs into each sequence element. |
|||
goalNum[3] = goalNum[1][1] * 1000 + goalNum[1][2] * 100 + goalNum[1][3] * 10 + goalNum[1][4] --convert digits to an integer |
|||
--and store it |
|||
procedure getInputAndProcess(integer stage = 1) --object = 1 sets default value for the parameter if it isn't specified |
|||
goalNum[2][1..4] = 0 --{0,0,0,0} --set these to unscaned (0) since the scanning will start over. |
|||
currentGuess[1][1..4] = 0 --{0,0,0,0} --these too, or they will contain old marks |
|||
currentGuess[2][1..4] = 0 |
|||
tries += 1 --equivalent to tries = tries + 1, but faster and shorter to write |
|||
bcData[1..2] = 0 -- {0,0} |
|||
if stage <= 1 then --if this process was run for the first time or with no parameters, then.. |
|||
puts(1,"The program has thought of a four digit number using only digits 1 to 9.\nType your guess and press enter.\n") |
|||
end if |
|||
while 1 label "guesscheck" do --labels can be used to specify a jump point from exit or retry, and help readability |
|||
currentGuess[1] = trim(gets(0), removeChars) --get user input, trim unwanted characters from it, store it in currentGuess[1] |
|||
currentGuess[1] = mapping( currentGuess[1], {49,50,51,52,53,54,55,56,57}, {1,2,3,4,5,6,7,8,9} ) --convert ascii codes to |
|||
-- integer digits they represent |
|||
integer tempF = find('0',currentGuess[1]) |
|||
if length(currentGuess[1]) != 4 or tempF != 0 then --if the input string is now more than 4 characters/integers, |
|||
--the input won't be used. |
|||
puts(1,"You probably typed too many digits or a 0. Try typing a new 4 digit number with only numbers 1 through 9.\n") |
|||
retry "guesscheck" |
|||
else |
|||
exit "guesscheck" |
|||
end if |
|||
end while |
|||
--convert separate digits to the one integer they represent and store it, like with goalNum[3] |
|||
currentGuess[3] = currentGuess[1][1] * 1000 + currentGuess[1][2] * 100 + currentGuess[1][3] * 10 + currentGuess[1][4] |
|||
--convert digits to the integer they represent, to print to a string later |
|||
--check for bulls |
|||
for i = 1 to 4 do |
|||
if goalNum[1][i] = currentGuess[1][i] then |
|||
goalNum[2][i] = 1 |
|||
currentGuess[2][i] = 1 |
|||
bcData[1] += 1 |
|||
end if |
|||
end for |
|||
--check for cows, but not slots marked as bulls or cows already. |
|||
for i = 1 to 4 label "iGuessElem"do --loop through each guessed digit |
|||
for j = 1 to 4 label "jGoalElem" do --but first go through each goal digit, comparing the first guessed digit, |
|||
--and then the other guessed digits 2 through 4 |
|||
if currentGuess[2][i] = 1 then --if the guessed digit we're comparing right now has been marked as bull or cow already |
|||
continue "iGuessElem" --skip to the next guess digit without comparing this guess digit to the other goal digits |
|||
end if |
|||
if goalNum[2][j] = 1 then --if the goal digit we're comparing to right now has been marked as a bull or cow already |
|||
continue "jGoalElem" --skip to the next goal digit |
|||
end if |
|||
if currentGuess[1][i] = goalNum[1][j] then --if the guessed digit is the same as the goal one, |
|||
--it won't be a bull, so it's a cow |
|||
bcData[2] += 1 --score one more cow |
|||
goalNum[2][j] = 1 --mark this digit as a found cow in the subsequence that stores 0's or 1's as flags |
|||
continue "iGuessElem" --skip to the next guess digit, so that this digit won't try to check for |
|||
--matches(cow) with other goal digits |
|||
end if |
|||
end for --this guess digit was compared to one goal digit , try comparing this guess digit with the next goal digit |
|||
end for --this guess digit was compared with all goal digits, compare the next guess digit to all the goal digits |
|||
if bcData[1] = 1 then --uses singular noun when there is score of 1, else plural |
|||
bcStrings[1] = "bull" |
|||
else |
|||
bcStrings[1] = "bulls" |
|||
end if |
|||
if bcData[2] = 1 then --the same kind of thing as above block |
|||
bcStrings[2] = "cow" |
|||
else |
|||
bcStrings[2] = "cows" |
|||
end if |
|||
if bcData[1] < 4 then --if less than 4 bulls were found, the player hasn't won, else they have... |
|||
printf(1, "Guess #%d : You guessed %d . You found %d %s, %d %s. Type new guess.\n", {tries, currentGuess[3], bcData[1], bcStrings[1], bcData[2], bcStrings[2]} ) |
|||
getInputAndProcess(2) |
|||
else --else they have won and the procedure ends |
|||
printf(1, "The number was %d. You guessed %d in %d tries.\n", {goalNum[3], currentGuess[3], tries} ) |
|||
any_key()--wait for keypress before closing console window. |
|||
end if |
|||
end procedure |
|||
--run the procedure |
|||
getInputAndProcess(1) |
|||
</syntaxhighlight> |
|||
Output : |
|||
<pre> |
|||
The program has thought of a four digit number using only digits 1 to 9. |
|||
Type your guess and press enter. |
|||
7456 |
|||
Guess #1 : You guessed 7456 . You found 1 bull, 1 cow. Type new guess. |
|||
7116 |
|||
Guess #2 : You guessed 7116 . You found 1 bull, 0 cows. Type new guess. |
|||
7862 |
|||
Guess #3 : You guessed 7862 . You found 0 bulls, 2 cows. Type new guess. |
|||
1826 |
|||
[...etc] |
|||
6586 |
|||
Guess #10 : You guessed 6586 . You found 3 bulls, 0 cows. Type new guess. |
|||
5586 |
|||
Guess #11 : You guessed 5586 . You found 3 bulls, 0 cows. Type new guess. |
|||
2586 |
|||
Guess #12 : You guessed 2586 . You found 3 bulls, 0 cows. Type new guess. |
|||
9586 |
|||
The number was 9586. You guessed 9586 in 13 tries. |
|||
Press Any Key to continue... |
|||
</pre> |
|||
=={{header|F Sharp|F#}}== |
|||
<syntaxhighlight lang="fsharp"> |
|||
open System |
|||
let generate_number targetSize = |
|||
let rnd = Random() |
|||
let initial = Seq.initInfinite (fun _ -> rnd.Next(1,9)) |
|||
initial |> Seq.distinct |> Seq.take(targetSize) |> Seq.toList |
|||
let countBulls guess target = |
|||
let hits = List.map2 (fun g t -> if g = t then true else false) guess target |
|||
List.filter (fun x -> x = true) hits |> List.length |
|||
let countCows guess target = |
|||
let mutable score = 0 |
|||
for g in guess do |
|||
for t in target do |
|||
if g = t then |
|||
score <- score + 1 |
|||
else |
|||
score <- score |
|||
score |
|||
let countScore guess target = |
|||
let bulls = countBulls guess target |
|||
let cows = countCows guess target |
|||
(bulls, cows) |
|||
let playRound guess target = |
|||
countScore guess target |
|||
let inline ctoi c : int = |
|||
int c - int '0' |
|||
let lineToList (line: string) = |
|||
let listc = Seq.map(fun c -> c |> string) line |> Seq.toList |
|||
let conv = List.map(fun x -> Int32.Parse x) listc |
|||
conv |
|||
let readLine() = |
|||
let line = Console.ReadLine() |
|||
if line <> null then |
|||
if line.Length = 4 then |
|||
Ok (lineToList line) |
|||
else |
|||
Error("Input guess must be 4 characters!") |
|||
else |
|||
Error("Input guess cannot be empty!") |
|||
let rec handleInput() = |
|||
let line = readLine() |
|||
match line with |
|||
| Ok x -> x |
|||
| Error s -> |
|||
printfn "%A" s |
|||
handleInput() |
|||
[<EntryPoint>] |
|||
let main argv = |
|||
let target = generate_number 4 |
|||
let mutable shouldEnd = false |
|||
while shouldEnd = false do |
|||
let guess = handleInput() |
|||
let (b, c) = playRound guess target |
|||
printfn "Bulls: %i | Cows: %i" b c |
|||
if b = 4 then |
|||
shouldEnd <- true |
|||
else |
|||
shouldEnd <- false |
|||
0 |
|||
</syntaxhighlight> |
|||
=={{Header|FreeBASIC}}== |
|||
<syntaxhighlight lang="text">function get_digit( num as uinteger, ps as uinteger ) as uinteger |
|||
return (num mod 10^(ps+1))\10^ps |
|||
end function |
|||
function is_malformed( num as uinteger ) as boolean |
|||
if num > 9876 then return true |
|||
dim as uinteger i, j |
|||
for i = 0 to 2 |
|||
for j = i+1 to 3 |
|||
if get_digit( num, j ) = get_digit( num, i ) then return true |
|||
next j |
|||
next i |
|||
return false |
|||
end function |
|||
function make_number() as uinteger |
|||
dim as uinteger num = 0 |
|||
while is_malformed(num) |
|||
num = int(rnd*9877) |
|||
wend |
|||
return num |
|||
end function |
|||
randomize timer |
|||
dim as uinteger count=0, num=make_number(), guess=0 |
|||
dim as uinteger cows, bulls, i, j |
|||
while guess <> num |
|||
count += 1 |
|||
do |
|||
print "Guess a number. " |
|||
input guess |
|||
loop while is_malformed(guess) |
|||
cows = 0 |
|||
bulls = 0 |
|||
for i = 0 to 3 |
|||
for j = 0 to 3 |
|||
if get_digit( num, i ) = get_digit( guess, j ) then |
|||
if i= j then bulls += 1 |
|||
if i<>j then cows += 1 |
|||
end if |
|||
next j |
|||
next i |
|||
print using "You scored # bulls and # cows."; bulls; cows |
|||
wend |
|||
print using "Correct. That took you ### guesses."; count</syntaxhighlight> |
|||
=={{header|Factor}}== |
|||
idiomatic style: |
|||
<syntaxhighlight lang="factor"> |
|||
USING: io kernel math math.parser random ranges sequences sets ; IN: bullsncows |
|||
9 [1..b] 4 sample [ 48 + ] "" map-as |
|||
[ "guess the 4-digit number: " write flush readln dup |
|||
[ length 4 = ] [ [ 48 57 [a..b] in? ] all? ] bi and ! [48,57] is the ascii range for 0-9 |
|||
[ 2dup = |
|||
[ 2drop "yep!" print flush f ] |
|||
[ "bulls & cows: " write |
|||
[ 0 [ = 1 0 ? + ] 2reduce ] [ intersect length ] 2bi over - |
|||
[ number>string ] bi@ " & " glue print flush t ] |
|||
if ] |
|||
[ 2drop "bad input" print t ] |
|||
if ] curry loop |
|||
</syntaxhighlight> |
|||
imperative/oop style: |
|||
<syntaxhighlight lang="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 ;</syntaxhighlight> |
|||
=={{header|Fan}}== |
=={{header|Fan}}== |
||
<syntaxhighlight lang="fan">** |
|||
<lang Fan> |
|||
** |
|||
** Bulls and cows. A game pre-dating, and similar to, Mastermind. |
** Bulls and cows. A game pre-dating, and similar to, Mastermind. |
||
** |
** |
||
Line 655: | Line 3,055: | ||
} |
} |
||
} |
} |
||
}</syntaxhighlight> |
|||
} |
|||
=={{header|FOCAL}}== |
|||
</lang> |
|||
<syntaxhighlight lang="focal">01.10 T %1,"BULLS AND COWS"!"----- --- ----"!! |
|||
01.20 S T=0;D 3 |
|||
01.30 D 2;D 5;S T=T+1;T "BULLS",B," COWS",C,!! |
|||
01.40 I (B-4)1.3 |
|||
01.50 T "YOU WON! GUESSES",%4,T,!! |
|||
01.60 Q |
|||
02.10 A "GUESS",A |
|||
02.20 F X=0,3;S B=FITR(A/10);S G(3-X)=A-B*10;S A=B |
|||
02.30 S A=1 |
|||
02.40 F X=0,3;S A=A*G(X) |
|||
02.50 I (-A)2.6;T "NEED FOUR NONZERO DIGITS"!;G 2.1 |
|||
02.60 F X=0,2;F Y=X+1,3;S A=A*(FABS(G(X)-G(Y))) |
|||
02.70 I (-A)2.8;T "NO DUPLICATES ALLOWED"!;G 2.1 |
|||
02.80 R |
|||
03.10 F X=0,3;S S(X)=0 |
|||
03.20 F X=0,3;D 4;S S(X)=A |
|||
04.10 S A=10*FRAN();S A=FITR(1+9*(A-FITR(A))) |
|||
04.20 S Z=1 |
|||
04.30 F Y=0,3;S Z=Z*(FABS(A-S(Y))) |
|||
04.40 I (-Z)4.5,4.1 |
|||
04.50 R |
|||
05.10 S B=0 |
|||
05.20 F X=0,3;D 5.6 |
|||
05.30 S C=-B |
|||
05.40 F X=0,3;F Y=0,3;D 5.7 |
|||
05.50 R |
|||
05.60 I (-FABS(S(X)-G(X)))5.5,5.8 |
|||
05.70 I (-FABS(S(X)-G(Y)))5.5,5.9 |
|||
05.80 S B=B+1 |
|||
05.90 S C=C+1</syntaxhighlight> |
|||
{{out}} |
|||
<pre>BULLS AND COWS |
|||
----- --- ---- |
|||
GUESS:1234 |
|||
BULLS= 0 COWS= 3 |
|||
GUESS:3214 |
|||
BULLS= 1 COWS= 2 |
|||
GUESS:3124 |
|||
BULLS= 2 COWS= 1 |
|||
GUESS:3145 |
|||
BULLS= 3 COWS= 0 |
|||
GUESS:3146 |
|||
BULLS= 3 COWS= 0 |
|||
GUESS:3147 |
|||
BULLS= 3 COWS= 0 |
|||
GUESS:3148 |
|||
BULLS= 3 COWS= 0 |
|||
GUESS:3149 |
|||
BULLS= 4 COWS= 0 |
|||
YOU WON! GUESSES= 8</pre> |
|||
=={{header|Forth}}== |
=={{header|Forth}}== |
||
{{works with|GNU Forth}} |
{{works with|GNU Forth}} |
||
<syntaxhighlight lang="forth">include random.fs |
|||
<lang forth> |
|||
include random.fs |
|||
create hidden 4 allot |
create hidden 4 allot |
||
Line 697: | Line 3,160: | ||
: guess: ( "1234" -- ) |
: guess: ( "1234" -- ) |
||
bl parse 2dup ok? 0= if 2drop ." Bad guess! (4 unique digits, 1-9)" exit then |
bl parse 2dup ok? 0= if 2drop ." Bad guess! (4 unique digits, 1-9)" exit then |
||
drop check? if cr ." You guessed it!" then ; |
drop check? if cr ." You guessed it!" then ;</syntaxhighlight> |
||
{{out}} |
|||
</lang> |
|||
<pre>init ok |
|||
guess: 1234 1 bulls, 0 cows ok |
guess: 1234 1 bulls, 0 cows ok |
||
guess: 1567 1 bulls, 1 cows ok |
guess: 1567 1 bulls, 1 cows ok |
||
guess: 1895 2 bulls, 1 cows ok |
guess: 1895 2 bulls, 1 cows ok |
||
guess: 1879 4 bulls, 0 cows |
guess: 1879 4 bulls, 0 cows |
||
You guessed it! ok |
You guessed it! ok</pre> |
||
=={{header|Fortran}}== |
=={{header|Fortran}}== |
||
{{works with|Fortran|90 and later}} |
{{works with|Fortran|90 and later}} |
||
< |
<syntaxhighlight lang="fortran">module bac |
||
implicit none |
implicit none |
||
Line 791: | Line 3,253: | ||
write(*,"(a,i0,a)") "Congratulations! You correctly guessed the correct number in ", tries, " attempts" |
write(*,"(a,i0,a)") "Congratulations! You correctly guessed the correct number in ", tries, " attempts" |
||
end program Bulls_and_Cows</ |
end program Bulls_and_Cows</syntaxhighlight> |
||
=={{header|Frink}}== |
|||
<syntaxhighlight lang="frink"> |
|||
// Bulls and Cows - Written in Frink |
|||
println["Welcome to Bulls and Cows!"] |
|||
// Put 4 random digits into target array |
|||
digits = array[1 to 9] |
|||
target = new array |
|||
for i = 0 to 3 |
|||
{ |
|||
target@i = digits.removeRandom[] |
|||
} |
|||
// Game variables |
|||
guessCount = 0 |
|||
solved = 0 |
|||
while solved == 0 |
|||
{ |
|||
// Round variables |
|||
bulls = 0 |
|||
cows = 0 |
|||
// Input guess from player |
|||
guess = input["Guess a 4 digit number with numbers 1 to 9: "] |
|||
// Valid Guess Tests. Set validGuess to 1. If any test fails it will be set to 0 |
|||
validGuess = 1 |
|||
// Test for exactly 4 digits |
|||
if length[guess] != 4 |
|||
{ |
|||
println["$guess is invalid. Your guess must be 4 digits."] |
|||
validGuess = 0 |
|||
} |
|||
// Test for any characters not in 1 - 9 using regex |
|||
if guess =~ %r/[^1-9]/ |
|||
{ |
|||
println["$guess is invalid. Your guess can only contain the digits 1 through 9."] |
|||
validGuess = 0 |
|||
} |
|||
// Check for duplicate digits in guess |
|||
comboCheck = 1 |
|||
guessArr = charList[guess] // Split guess string into array of characters. |
|||
guessArrCombos = guessArr.combinations[2] // Divide the array into all possible 2 digits combinations. |
|||
for geussCombo = guessArrCombos |
|||
{ |
|||
if geussCombo@0 == geussCombo@1 // If the two digits in the combinations are the same mark the comboCheck as failed. |
|||
comboCheck = 0 |
|||
} |
|||
if comboCheck == 0 |
|||
{ |
|||
println["$guess is invalid. Each digit in your guess should be unique."] |
|||
validGuess = 0 |
|||
} |
|||
// If all tests pass, continue with the game. |
|||
if validGuess == 1 |
|||
{ |
|||
guessCount = guessCount + 1 |
|||
for i = 0 to 3 |
|||
{ |
|||
if parseInt[guessArr@i] == target@i // Convert guess from string to int. Frink imports all input as strings. |
|||
{ |
|||
bulls = bulls + 1 |
|||
next // If bull is found, skip the contains check. |
|||
} |
|||
if target.contains[parseInt[guessArr@i]] |
|||
{ |
|||
cows = cows + 1 |
|||
} |
|||
} |
|||
if bulls == 4 |
|||
{ |
|||
solved = 1 // Exit from While loop. |
|||
} else |
|||
{ |
|||
// Print the results of the guess. Formatting for plurals. |
|||
bullsPlural = bulls == 1 ? "bull" : "bulls" |
|||
cowsPlural = cows == 1 ? "cow" : "cows" |
|||
println["Your guess of $guess had $bulls $bullsPlural and $cows $cowsPlural."] |
|||
} |
|||
} |
|||
} |
|||
guessPlural = guessCount == 1 ? "guess" : "guesses" |
|||
println["Congratulations! Your guess of $guess was correct! You solved this in $guessCount $guessPlural."] |
|||
</syntaxhighlight> |
|||
{{Out}} |
|||
<pre> |
|||
Welcome to Bulls and Cows! |
|||
Your guess of 1234 had 1 bull and 2 cows. |
|||
Your guess of 5678 had 0 bulls and 1 cow. |
|||
Your guess of 2345 had 0 bulls and 2 cows. |
|||
Your guess of 3261 had 1 bull and 2 cows. |
|||
Your guess of 4173 had 0 bulls and 3 cows. |
|||
Your guess of 8231 had 2 bulls and 0 cows. |
|||
Your guess of 7134 had 1 bull and 2 cows. |
|||
Your guess of 3461 had 2 bulls and 2 cows. |
|||
Congratulations! Your guess of 6431 was correct! You solved this in 9 guesses. |
|||
</pre> |
|||
=={{header|FutureBasic}}== |
|||
<syntaxhighlight lang="futurebasic"> |
|||
include "NSLog.incl" |
|||
str15 guess, goal |
|||
short x, y |
|||
cgRect wndrect |
|||
begin enum 1 |
|||
_window |
|||
_bullLabel |
|||
_cowLabel |
|||
_horzLine |
|||
_vertLine |
|||
_newGameBtn |
|||
_alert = 101 |
|||
end enum |
|||
void local fn showStr( string as str15 ) |
|||
short r |
|||
x = 20 |
|||
for r = 1 to string[0] |
|||
print %(x,y)chr$( string[r] ); |
|||
x += 39 |
|||
next |
|||
end fn |
|||
void local fn NewGame |
|||
str15 ch |
|||
goal = "" : guess = "" :y = 20 |
|||
window _window,,wndRect |
|||
text ,,fn colorRed |
|||
cls |
|||
fn showStr( "????" ) |
|||
do |
|||
ch = chr$(rnd(9) or _"0") |
|||
if instr$(0, goal, ch) == 0 then goal += ch |
|||
until goal[0] == 4 |
|||
nslog(@"%u",val&(goal)) //unrem for testing |
|||
y += 48 |
|||
end fn |
|||
local fn SetWindowFrame |
|||
CGRect r = fn WindowContentRect( _window ) |
|||
r.size.height += 32 |
|||
r.origin.y -= 32 |
|||
window _window,,r |
|||
if ( r.origin.y < 150 ) |
|||
alert _alert,, @"Too many guesses!",, @"Give up", YES |
|||
fn newGame |
|||
end if |
|||
end fn |
|||
local fn play( ch as str15 ) |
|||
short r, bulls = 0, cows = 0 |
|||
if instr$(0, guess, ch) then exit fn |
|||
guess += ch |
|||
text,,fn colorDarkGray |
|||
fn showStr( guess ) |
|||
if guess[0] < 4 then exit fn |
|||
for r = 1 to 4 |
|||
if goal[r] == guess[r] then bulls++ : continue |
|||
if instr$(0, goal, chr$(guess[r]) ) then cows++ |
|||
next |
|||
select |
|||
case bulls == 4 |
|||
text ,,fn colorRed |
|||
print %(x + 31, y)("W I N!") |
|||
y = 20 : fn showStr( goal ) |
|||
case else : print %(x + 35, y)bulls;" "; cows |
|||
y += 32 : guess = "" |
|||
end select |
|||
fn SetWindowFrame |
|||
end fn |
|||
void local fn BuildWindow |
|||
subclass window _window, @"Bulls and cows", (0,0,311,114), NSWindowStyleMaskTitled + NSWindowStyleMaskClosable |
|||
wndrect = = fn WindowContentRect( _window ) |
|||
textlabel _bullLabel, @"🐂", (198,59,38,40) |
|||
textlabel _cowLabel, @"🐄", (255,59,38,40) |
|||
ControlSetFontWithName( _bullLabel, NULL, 30 ) |
|||
ControlSetFontWithName( _cowLabel, NULL, 30 ) |
|||
box _horzLine,, (12,50,287,5), NSBoxSeparator |
|||
box _vertLine,, (180,12,5,90), NSBoxSeparator |
|||
ViewSetAutoresizingMask( _vertLine, NSViewHeightSizable ) |
|||
button _newGameBtn,,, @"New Game", (198,13,100,32) |
|||
ViewSetAutoresizingMask( _newGameBtn, NSViewMaxYMargin ) |
|||
text @"menlo bold",24,,fn ColorWindowBackground |
|||
end fn |
|||
void local fn DoDialog( evt as long, tag as long ) |
|||
select ( evt ) |
|||
case _windowKeyDown //: stop |
|||
short ch = intval( fn EventCharacters ) |
|||
if ch then fn play( chr$( ch or _"0" ) ):DialogEventSetBool(YES) |
|||
case _btnClick : fn NewGame |
|||
case _windowWillClose : end |
|||
end select |
|||
end fn |
|||
on dialog fn DoDialog |
|||
fn buildWindow |
|||
fn newGame |
|||
HandleEvents |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
[[File:Bulls and Cows in FutureBasic.png]] |
|||
=={{header|Go}}== |
|||
<syntaxhighlight lang="go">package main |
|||
import ( |
|||
"bufio" |
|||
"bytes" |
|||
"fmt" |
|||
"math/rand" |
|||
"os" |
|||
"strings" |
|||
"time" |
|||
) |
|||
func main() { |
|||
fmt.Println(`Cows and Bulls |
|||
Guess four digit number of unique digits in the range 1 to 9. |
|||
A correct digit but not in the correct place is a cow. |
|||
A correct digit in the correct place is a bull.`) |
|||
// generate pattern |
|||
pat := make([]byte, 4) |
|||
rand.Seed(time.Now().Unix()) |
|||
r := rand.Perm(9) |
|||
for i := range pat { |
|||
pat[i] = '1' + byte(r[i]) |
|||
} |
|||
// accept and score guesses |
|||
valid := []byte("123456789") |
|||
guess: |
|||
for in := bufio.NewReader(os.Stdin); ; { |
|||
fmt.Print("Guess: ") |
|||
guess, err := in.ReadString('\n') |
|||
if err != nil { |
|||
fmt.Println("\nSo, bye.") |
|||
return |
|||
} |
|||
guess = strings.TrimSpace(guess) |
|||
if len(guess) != 4 { |
|||
// malformed: not four characters |
|||
fmt.Println("Please guess a four digit number.") |
|||
continue |
|||
} |
|||
var cows, bulls int |
|||
for ig, cg := range guess { |
|||
if strings.IndexRune(guess[:ig], cg) >= 0 { |
|||
// malformed: repeated digit |
|||
fmt.Printf("Repeated digit: %c\n", cg) |
|||
continue guess |
|||
} |
|||
switch bytes.IndexByte(pat, byte(cg)) { |
|||
case -1: |
|||
if bytes.IndexByte(valid, byte(cg)) == -1 { |
|||
// malformed: not a digit |
|||
fmt.Printf("Invalid digit: %c\n", cg) |
|||
continue guess |
|||
} |
|||
default: // I just think cows should go first |
|||
cows++ |
|||
case ig: |
|||
bulls++ |
|||
} |
|||
} |
|||
fmt.Printf("Cows: %d, bulls: %d\n", cows, bulls) |
|||
if bulls == 4 { |
|||
fmt.Println("You got it.") |
|||
return |
|||
} |
|||
} |
|||
}</syntaxhighlight> |
|||
=={{header|Golo}}== |
|||
<syntaxhighlight lang="golo">#!/usr/bin/env golosh |
|||
---- |
|||
This module is the Bulls and Cows game. |
|||
---- |
|||
module Bullsandcows |
|||
import gololang.Decorators |
|||
import gololang.Functions |
|||
import gololang.IO |
|||
import java.util |
|||
function main = |args| { |
|||
while true { |
|||
let secret = create4RandomNumbers() |
|||
println("Welcome to Bulls And Cows") |
|||
while true { |
|||
println("Please enter a 4 digit number") |
|||
println("(with only the digits 1 to 9 and no repeated digits, for example 2537)") |
|||
let guess = readln("guess: ") |
|||
let result = validateGuess(guess) |
|||
if result: isValid() { |
|||
let bulls, cows = bullsAndOrCows(result: digits(), secret) |
|||
if bulls is 4 { |
|||
println("You win!") |
|||
break |
|||
} |
|||
println("bulls: " + bulls) |
|||
println("cows: " + cows) |
|||
} else { |
|||
println(result: message()) |
|||
} |
|||
} |
|||
} |
|||
} |
|||
function create4RandomNumbers = { |
|||
let numbers = vector[1, 2, 3, 4, 5, 6, 7, 8, 9] |
|||
Collections.shuffle(numbers) |
|||
let shuffled = numbers: subList(0, 4) |
|||
return shuffled |
|||
} |
|||
union Result = { |
|||
Valid = { digits } |
|||
Invalid = { message } |
|||
} |
|||
@checkArguments(isString()) |
|||
function validateGuess = |guess| { |
|||
var digits = [] |
|||
try { |
|||
let number = guess: toInt() |
|||
digits = number: digits() |
|||
if digits: exists(|d| -> d is 0) { |
|||
return Result.Invalid("No zeroes please") |
|||
} |
|||
if digits: size() isnt 4 { |
|||
return Result.Invalid("Four digits please") |
|||
} |
|||
let digitSet = set[ digit foreach digit in digits ] |
|||
if digitSet: size() < digits: size() { |
|||
return Result.Invalid("No duplicate numbers please") |
|||
} |
|||
} catch(e) { |
|||
return Result.Invalid("Numbers only please") |
|||
} |
|||
return Result.Valid(digits) |
|||
} |
|||
let is4Vector = |arg| -> arg oftype java.util.List.class and arg: size() is 4 |
|||
@checkArguments(is4Vector, is4Vector) |
|||
function bullsAndOrCows = |guess, secret| { |
|||
var bulls = 0 |
|||
var cows = 0 |
|||
foreach i in [0..4] { |
|||
let guessNum = guess: get(i) |
|||
let secretNum = secret: get(i) |
|||
if guessNum is secretNum { |
|||
bulls = bulls + 1 |
|||
} else if secret: exists(|num| -> guessNum is num) { |
|||
cows = cows + 1 |
|||
} |
|||
} |
|||
return [bulls, cows] |
|||
} |
|||
augment java.lang.Integer { |
|||
function digits = |this| { |
|||
var remaining = this |
|||
let digits = vector[] |
|||
while remaining > 0 { |
|||
digits: prepend(remaining % 10) |
|||
remaining = remaining / 10 |
|||
} |
|||
return digits |
|||
} |
|||
} |
|||
</syntaxhighlight> |
|||
=={{header|Groovy}}== |
|||
<syntaxhighlight lang="groovy">class BullsAndCows { |
|||
static void main(args) { |
|||
def inputReader = System.in.newReader() |
|||
def numberGenerator = new Random() |
|||
def targetValue |
|||
while (targetValueIsInvalid(targetValue = numberGenerator.nextInt(9000) + 1000)) continue |
|||
def targetStr = targetValue.toString() |
|||
def guessed = false |
|||
def guesses = 0 |
|||
while (!guessed) { |
|||
def bulls = 0, cows = 0 |
|||
print 'Guess a 4-digit number with no duplicate digits: ' |
|||
def guess = inputReader.readLine() |
|||
if (guess.length() != 4 || !guess.isInteger() || targetValueIsInvalid(guess.toInteger())) { |
|||
continue |
|||
} |
|||
guesses++ |
|||
4.times { |
|||
if (targetStr[it] == guess[it]) { |
|||
bulls++ |
|||
} else if (targetStr.contains(guess[it])) { |
|||
cows++ |
|||
} |
|||
} |
|||
if (bulls == 4) { |
|||
guessed = true |
|||
} else { |
|||
println "$cows Cows and $bulls Bulls." |
|||
} |
|||
} |
|||
println "You won after $guesses guesses!" |
|||
} |
|||
static targetValueIsInvalid(value) { |
|||
def digitList = [] |
|||
while (value > 0) { |
|||
if (digitList[value % 10] == 0 || digitList[value % 10]) { |
|||
return true |
|||
} |
|||
digitList[value % 10] = true |
|||
value = value.intdiv(10) |
|||
} |
|||
false |
|||
} |
|||
} |
|||
</syntaxhighlight> |
|||
=={{header|Haskell}}== |
|||
<syntaxhighlight lang="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</syntaxhighlight> |
|||
=={{header|Hy}}== |
|||
<syntaxhighlight lang="lisp">(import random) |
|||
(def +size+ 4) |
|||
(def +digits+ "123456789") |
|||
(def +secret+ (random.sample +digits+ +size+)) |
|||
(while True |
|||
(while True |
|||
(setv guess (list (distinct (raw-input "Enter a guess: ")))) |
|||
(when (and |
|||
(= (len guess) +size+) |
|||
(all (map (fn [c] (in c +digits+)) guess))) |
|||
(break)) |
|||
(print "Malformed guess; try again")) |
|||
(setv bulls 0) |
|||
(setv cows 0) |
|||
(for [i (range +size+)] (cond |
|||
[(= (get guess i) (get +secret+ i)) (setv bulls (inc bulls))] |
|||
[(in (get guess i) +secret+) (setv cows (inc cows))])) |
|||
(when (= bulls +size+) |
|||
(break)) |
|||
(print (.format "{} bull{}, {} cows" |
|||
bulls (if (= bulls 1) "" "s") |
|||
cows (if (= cows 1) "" "s")))) |
|||
(print "A winner is you!")</syntaxhighlight> |
|||
=={{header|Icon}} and {{header|Unicon}}== |
|||
The following works in both Icon and Unicon. |
|||
<syntaxhighlight lang="unicon">procedure main() |
|||
digits := "123456789" |
|||
every !digits :=: ?digits |
|||
num := digits[1+:4] |
|||
repeat if score(num, getGuess(num)) then break |
|||
write("Good job.") |
|||
end |
|||
procedure getGuess(num) |
|||
repeat { |
|||
writes("Enter a guess: ") |
|||
guess := read() | stop("Quitter!") |
|||
if *(guess ** '123456789') == *num then return guess |
|||
write("Malformed guess: ",guess,". Try again.") |
|||
} |
|||
end |
|||
procedure score(num, guess) |
|||
bulls := 0 |
|||
cows := *(num ** guess) |
|||
every (num[i := 1 to *num] == guess[i], bulls +:= 1, cows -:= 1) |
|||
write("\t",bulls," bulls and ",cows," cows") |
|||
return (bulls = *num) |
|||
end</syntaxhighlight> |
|||
=={{header|J}}== |
=={{header|J}}== |
||
{{trans|APL}} |
|||
<lang J>require 'misc' |
|||
A tacit recursive functional version. To play, call <code>moo</code> with a dummy argument. |
|||
<syntaxhighlight lang="j"> |
|||
output=. [ 'Bulls: '&,:@'Cows: ' echo@,. ":@,. |
|||
valid =. *./@e.&'0123456789' *. 4 = # |
|||
guess =. [: ".&> :: ] $:^:(-.@valid)@(1!:1@1)@echo@'Guess:' |
|||
game =. [ $:^:(4 0-.@-:]) [ (+/@:= output@, e.+/@:*.~:) guess |
|||
moo =. 'You win!'[ (1+4?9:) game ] |
|||
</syntaxhighlight> |
|||
An expanded version that uses iteration instead of recursion: |
|||
<syntaxhighlight lang="j"> |
|||
U =. [ F.([.[(_2:Z:].)) NB. u until v |
|||
input =. 1!:1@1@echo@'Guess: ' |
|||
output =. [ ('Bulls: ',:'Cows: ')echo@,.":@,. |
|||
isdigits=. *./@e.&'0123456789' |
|||
valid =. isdigits*.4=# |
|||
guess =. [:".&>input U(valid@]) |
|||
bulls =. +/@:= |
|||
cows =. [:+/e.*.~: |
|||
game =. ([:output [(bulls,cows) guess)U(4 0-:]) |
|||
random =. 1+4?9: |
|||
moo =. 'You win!'[ random game ] |
|||
</syntaxhighlight> |
|||
Fold (<code>F.</code>) is used instead of <code>Until=. [.^:(-.@:].)^:_</code> because the latter would exit the loop if two consecutive iterations produced the same output. |
|||
In real applications, <code>a.&i.-48"_</code> should be used instead of <code>".</code> to safely convert character input to a numeric array. |
|||
A version that uses imperative control flow: |
|||
<syntaxhighlight lang="j">require 'misc' |
|||
plural=: conjunction define |
plural=: conjunction define |
||
(":m),' ',n,'s'#~1~:m |
(":m),' ',n,'s'#~1~:m |
||
) |
) |
||
bullcow=:monad define |
bullcow=:monad define |
||
number=. 1+4?9 |
number=. 1+4?9 |
||
guess |
whilst. -.guess-:number do. |
||
guess=. 0 "."0 prompt 'Guess my number: ' |
|||
guess=.0 "."0 prompt 'Guess my number: ' |
|||
if. (4~:#guess)+.(4~:#~.guess)+.0 e.guess e.1+i.9 do. |
if. (4~:#guess)+.(4~:#~.guess)+.0 e.guess e.1+i.9 do. |
||
if.0=#guess do. |
if. 0=#guess do. |
||
smoutput 'Giving up.' |
smoutput 'Giving up.' |
||
return. |
return. |
||
Line 818: | Line 3,847: | ||
end. |
end. |
||
smoutput 'you win' |
smoutput 'you win' |
||
)</ |
)</syntaxhighlight> |
||
For example: |
|||
<syntaxhighlight lang="j"> bullcow'' |
|||
Guess my number: 1234 |
|||
0 bulls and 1 cow. |
|||
Guess my number: 5678 |
|||
3 bulls and 0 cows. |
|||
Guess my number: 2349 |
|||
0 bulls and 0 cows. |
|||
Guess my number: 1567 |
|||
0 bulls and 3 cows. |
|||
Guess my number: 6178 |
|||
3 bulls and 0 cows. |
|||
Guess my number: 6157 |
|||
1 bull and 2 cows. |
|||
Guess my number: 5178 |
|||
4 bulls and 0 cows. |
|||
you win</syntaxhighlight> |
|||
=={{header|Java}}== |
=={{header|Java}}== |
||
< |
<syntaxhighlight lang="java5">import java.util.InputMismatchException; |
||
import java.util.Random; |
import java.util.Random; |
||
import java.util.Scanner; |
import java.util.Scanner; |
||
Line 827: | Line 3,876: | ||
public static void main(String[] args){ |
public static void main(String[] args){ |
||
Random gen= new Random(); |
Random gen= new Random(); |
||
int target |
int target; |
||
while(hasDupes(target= (gen.nextInt(9000) + 1000))); |
while(hasDupes(target= (gen.nextInt(9000) + 1000))); |
||
String targetStr = target +""; |
String targetStr = target +""; |
||
Line 871: | Line 3,920: | ||
return false; |
return false; |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
Output: |
Output: |
||
<pre>Guess a 4-digit number with no duplicate digits: 5834 |
<pre>Guess a 4-digit number with no duplicate digits: 5834 |
||
Line 893: | Line 3,942: | ||
Guess a 4-digit number with no duplicate digits: 3957 |
Guess a 4-digit number with no duplicate digits: 3957 |
||
You won after 10 guesses!</pre> |
You won after 10 guesses!</pre> |
||
=={{header|JavaScript}}== |
|||
=== Spidermonkey version === |
|||
<syntaxhighlight lang="javascript">#!/usr/bin/env js |
|||
function main() { |
|||
var len = 4; |
|||
playBullsAndCows(len); |
|||
} |
|||
function playBullsAndCows(len) { |
|||
var num = pickNum(len); |
|||
// print('The secret number is:\n ' + num.join('\n ')); |
|||
showInstructions(len); |
|||
var nGuesses = 0; |
|||
while (true) { |
|||
nGuesses++; |
|||
var guess = getGuess(nGuesses, len); |
|||
var census = countBovine(num, guess); |
|||
showScore(census.bulls, census.cows); |
|||
if (census.bulls == len) { |
|||
showFinalResult(nGuesses); |
|||
return; |
|||
} |
|||
} |
|||
} |
|||
function showScore(nBulls, nCows) { |
|||
print(' Bulls: ' + nBulls + ', cows: ' + nCows); |
|||
} |
|||
function showFinalResult(guesses) { |
|||
print('You win!!! Guesses needed: ' + guesses); |
|||
} |
|||
function countBovine(num, guess) { |
|||
var count = {bulls:0, cows:0}; |
|||
var g = guess.join(''); |
|||
for (var i = 0; i < num.length; i++) { |
|||
var digPresent = g.search(num[i]) != -1; |
|||
if (num[i] == guess[i]) count.bulls++; |
|||
else if (digPresent) count.cows++; |
|||
} |
|||
return count; |
|||
} |
|||
function getGuess(nGuesses, len) { |
|||
while (true) { |
|||
putstr('Your guess #' + nGuesses + ': '); |
|||
var guess = readline(); |
|||
guess = String(parseInt(guess)).split(''); |
|||
if (guess.length != len) { |
|||
print(' You must enter a ' + len + ' digit number.'); |
|||
continue; |
|||
} |
|||
if (hasDups(guess)) { |
|||
print(' No digits can be duplicated.'); |
|||
continue; |
|||
} |
|||
return guess; |
|||
} |
|||
} |
|||
function hasDups(ary) { |
|||
var t = ary.concat().sort(); |
|||
for (var i = 1; i < t.length; i++) { |
|||
if (t[i] == t[i-1]) return true; |
|||
} |
|||
return false; |
|||
} |
|||
function showInstructions(len) { |
|||
print(); |
|||
print('Bulls and Cows Game'); |
|||
print('-------------------'); |
|||
print(' You must guess the ' + len + ' digit number I am thinking of.'); |
|||
print(' The number is composed of the digits 1-9.'); |
|||
print(' No digit appears more than once.'); |
|||
print(' After each of your guesses, I will tell you:'); |
|||
print(' The number of bulls (digits in right place)'); |
|||
print(' The number of cows (correct digits, but in the wrong place)'); |
|||
print(); |
|||
} |
|||
function pickNum(len) { |
|||
var nums = [1, 2, 3, 4, 5, 6, 7, 8, 9]; |
|||
nums.sort(function(){return Math.random() - 0.5}); |
|||
return nums.slice(0, len); |
|||
} |
|||
main(); |
|||
</syntaxhighlight> |
|||
Example game (cheating!): |
|||
Bulls and Cows Game |
|||
------------------- |
|||
You must guess the 4 digit number I am thinking of. |
|||
The number is composed of the digits 1-9. |
|||
No digit appears more than once. |
|||
After each of your guesses, I will tell you: |
|||
The number of bulls (digits in right place) |
|||
The number of cows (correct digits, but in wrong place) |
|||
Your guess #1: 1234 |
|||
Bulls: 0, cows: 2 |
|||
Your guess #2: 5678 |
|||
Bulls: 1, cows: 1 |
|||
Your guess #3: 3167 |
|||
Bulls: 0, cows: 3 |
|||
Your guess #4: 9123 |
|||
Bulls: 1, cows: 1 |
|||
Your guess #5: 5137 |
|||
Bulls: 1, cows: 3 |
|||
Your guess #6: 5317 |
|||
Bulls: 2, cows: 2 |
|||
Your guess #7: 5731 |
|||
Bulls: 2, cows: 2 |
|||
Your guess #8: 5713 |
|||
Bulls: 4, cows: 0 |
|||
You win! Guesses needed: 8 |
|||
=={{header|jq}}== |
|||
{{works with|jq}} |
|||
'''Also works with gojq, the Go implementation of jq.''' |
|||
'''Adapted from [[#Wren|Wren]]''' |
|||
The following program reads the user's input from STDIN, and reads |
|||
random digits from /dev/random using the --slurpfile command-line |
|||
option. This makes the program more convoluted than would have been |
|||
the case had the generation of the initial four-digit pseudo-random |
|||
integer been done in a separate step, but it does illustrate how |
|||
the limitations of jq's I/O can be circumvented |
|||
in this case. |
|||
In a bash or bash-like environment, a suitable invocation |
|||
would be as follows: |
|||
<pre> |
|||
jq -nrR --slurpfile raw <(< /dev/random tr -cd '0-9' | fold -w 1 | head -n 100) -f bc.jq |
|||
</pre> |
|||
'''bc.jq''' |
|||
<syntaxhighlight lang=jq> |
|||
# A PRNG for generating a pseudo-random integer in range(0; .). |
|||
# $array must be a sufficiently large array of pseudo-random integers in range(0;10). |
|||
# $start specifies the position in $array to begin searching. |
|||
# Output: {prn, start) where .prn is a PRN in range(0; .) and .start is the corresponding position in $array. |
|||
def prn($array; $start): |
|||
def a2n: map(tostring) | join("") | tonumber; |
|||
if . == 1 then 0 |
|||
else . as $n |
|||
| (($n-1)|tostring|length) as $w |
|||
| {$start} |
|||
| until( $array[.start: .start + $w] | a2n < $n; .start+=1 ) |
|||
| {start, prn: ($raw[.start: .start + $w] | a2n)} |
|||
end; |
|||
# Generate a 4-digit PRN from 1234 to 9876 inclusive, with no zeros or repeated digits. |
|||
# Global variable: $raw (see documentation for $array above) |
|||
def num: |
|||
def _num($start): |
|||
(8643|prn($raw; $start)) as $prn |
|||
| (1234 + $prn.prn) |
|||
| . as $n |
|||
| tostring |
|||
| if (test("0")|not) and ((explode|unique|length) == 4) |
|||
then $n |
|||
else _num($prn.start+4) |
|||
end; |
|||
_num(0); |
|||
def MAX_GUESSES: 20; # say |
|||
def instructions: |
|||
"All guesses should have exactly 4 distinct digits excluding zero.", |
|||
"Keep guessing until you guess the chosen number (maximum \(MAX_GUESSES) valid guesses).\n"; |
|||
def play: |
|||
num as $num |
|||
| ($num|tostring|explode) as $numArray |
|||
| { guesses: 0 } |
|||
| instructions, "Enter your guess:", |
|||
(label $out |
|||
| foreach range(0; infinite) as $i (.; |
|||
if .bulls == 4 or .guesses == MAX_GUESSES then break $out |
|||
else .guess = input |
|||
| if .guess == $num then .emit = "You have won with \(.guesses+1) valid guesses!" |
|||
else .n = (.guess | try tonumber catch null) |
|||
| if .n == null then .emit = "Not a valid number" |
|||
elif .guess|test("[+-.]") then .emit = "The guess should not contain a sign or decimal point." |
|||
elif .guess|test("0") then .emit = "The guess cannot contain zero." |
|||
elif .guess|length != 4 then .emit = "The guess must have exactly 4 digits." |
|||
else .guessArray = (.guess | explode ) |
|||
| if .guessArray | unique | length < 4 then .emit = "All digits must be distinct." |
|||
else . + {bulls: 0, cows: 0 } |
|||
| reduce range(0; .guessArray|length) as $i ( .; |
|||
if $numArray[$i] == .guessArray[$i] then .bulls += 1 |
|||
elif (.guessArray[$i] | IN($numArray[])) then .cows += 1 |
|||
else . |
|||
end) |
|||
| .emit = "Your score for this guess: Bulls = \(.bulls) Cows = \(.cows)" |
|||
| .guesses += 1 |
|||
end |
|||
end |
|||
end |
|||
end; |
|||
select(.emit).emit, |
|||
if .bulls == 4 then "Congratulations!" |
|||
elif .guesses == MAX_GUESSES |
|||
then "\nYou have now had \(.guesses) valid guesses, the maximum allowed. Bye!" |
|||
else "Enter your next guess:" |
|||
end ) ); |
|||
play |
|||
</syntaxhighlight> |
|||
=={{header|Julia}}== |
|||
<syntaxhighlight lang="julia">function cowsbulls() |
|||
print("Welcome to Cows & Bulls! I've picked a number with unique digits between 1 and 9, go ahead and type your guess.\n |
|||
You get one bull for every right number in the right position.\n |
|||
You get one cow for every right number, but in the wrong position.\n |
|||
Enter 'n' to pick a new number and 'q' to quit.\n>") |
|||
function new_number() |
|||
s = [1:9] |
|||
n = "" |
|||
for i = 9:-1:6 |
|||
n *= string(delete!(s,rand(1:i))) |
|||
end |
|||
return n |
|||
end |
|||
answer = new_number() |
|||
while true |
|||
input = chomp(readline(STDIN)) |
|||
input == "q" && break |
|||
if input == "n" |
|||
answer = new_number() |
|||
print("\nI've picked a new number, go ahead and guess\n>") |
|||
continue |
|||
end |
|||
!ismatch(r"^[1-9]{4}$",input) && (print("Invalid guess: Please enter a 4-digit number\n>"); continue) |
|||
if input == answer |
|||
print("\nYou're right! Good guessing!\nEnter 'n' for a new number or 'q' to quit\n>") |
|||
else |
|||
bulls = sum(answer.data .== input.data) |
|||
cows = sum([answer[x] != input[x] && contains(input.data,answer[x]) for x = 1:4]) |
|||
print("\nNot quite! Your guess is worth:\n$bulls Bulls\n$cows Cows\nPlease guess again\n\n>") |
|||
end |
|||
end |
|||
end</syntaxhighlight> |
|||
The following version checks thoroughly that the input of the player is constituted of four distincts digits. |
|||
<syntaxhighlight lang="julia">function bullsandcows () |
|||
bulls = cows = turns = 0 |
|||
result = (s = [] ; while length(unique(s))<4 push!(s,rand('1':'9')) end; unique(s)) |
|||
println("A game of bulls and cows!") |
|||
while (bulls != 4) |
|||
print("Your guess? ") |
|||
guess = collect(chomp(readline(STDIN))) |
|||
if ! (length(unique(guess)) == length(guess) == 4 && all(isdigit,guess)) |
|||
println("please, enter four distincts digits") |
|||
continue |
|||
end |
|||
bulls = sum(map(==, guess, result)) |
|||
cows = length(intersect(guess,result)) - bulls |
|||
println("$bulls bulls and $cows cows!") ; turns += 1 |
|||
end |
|||
println("You win! You succeeded in $turns guesses.") |
|||
end</syntaxhighlight> |
|||
{{Out}} |
|||
<pre>julia> bullsandcows() |
|||
A game of bulls and cows! |
|||
Your guess? 1234 |
|||
0 bulls and 2 cows! |
|||
Your guess? 12334 |
|||
please, enter four distincts digits |
|||
Your guess? 5678 |
|||
1 bulls and 1 cows! |
|||
Your guess? 1111 |
|||
please, enter four distincts digits |
|||
Your guess? grr |
|||
please, enter four distincts digits |
|||
Your guess? ... |
|||
please, enter four distincts digits |
|||
Your guess? </pre> |
|||
=={{header|K}}== |
|||
run in ngn/k. |
|||
<syntaxhighlight lang="k"> |
|||
n:1+-4?9 |
|||
loop:{ |
|||
`1:"guess: ";g:(`i$-1_1:`)-48 / -48 to convert ascii digit codepoints to corresponding int values |
|||
$[n~g;[`0:"yup!";`exit 0] |
|||
(4=#g)&*/(g<10)&~g<0;`0:"bulls & cows: "," & "/$(b;(#g^g^n)-b:+/n=g) |
|||
`0:"bad input"]} |
|||
{1}loop/0 / "while true: loop". 0 is a dummy arg |
|||
</syntaxhighlight> |
|||
=={{header|Kotlin}}== |
|||
<syntaxhighlight lang="kotlin"> |
|||
const val MAX_GUESSES = 20 // say |
|||
fun main() { |
|||
val num = ('1'..'9').shuffled().take(4).joinToString("") |
|||
println("All guesses should have exactly 4 distinct digits excluding zero.") |
|||
println("Keep guessing until you guess the chosen number (maximum $MAX_GUESSES valid guesses).\n") |
|||
var guesses = 0 |
|||
while (true) { |
|||
print("Enter your guess : ") |
|||
val guess = readln().trim() |
|||
if (guess == num) { |
|||
println("You've won with ${++guesses} valid guesses!") |
|||
break |
|||
} |
|||
val n = guess.toIntOrNull() |
|||
if (n == null) |
|||
println("Not a valid number") |
|||
else if ('-' in guess || '+' in guess) |
|||
println("Can't contain a sign") |
|||
else if ('0' in guess) |
|||
println("Can't contain zero") |
|||
else if (guess.length != 4) |
|||
println("Must have exactly 4 digits") |
|||
else if (guess.toSet().size < 4) |
|||
println("All digits must be distinct") |
|||
else { |
|||
var bulls = 0 |
|||
var cows = 0 |
|||
for ((i, c) in guess.withIndex()) { |
|||
if (num[i] == c) bulls++ |
|||
else if (c in num) cows++ |
|||
} |
|||
println("Your score for this guess: Bulls = $bulls Cows = $cows") |
|||
guesses++ |
|||
if (guesses == MAX_GUESSES) |
|||
println("You've now had $guesses valid guesses, the maximum allowed") |
|||
} |
|||
} |
|||
}</syntaxhighlight> |
|||
Sample input/output: |
|||
{{out}} |
|||
<pre> |
|||
Enter your guess : 1234 |
|||
Your score for this guess: Bulls = 0 Cows = 2 |
|||
Enter your guess : 1256 |
|||
Your score for this guess: Bulls = 0 Cows = 2 |
|||
Enter your guess : 2178 |
|||
Your score for this guess: Bulls = 1 Cows = 0 |
|||
Enter your guess : 2519 |
|||
Your score for this guess: Bulls = 3 Cows = 0 |
|||
Enter your guess : 2569 |
|||
Your score for this guess: Bulls = 3 Cows = 0 |
|||
Enter your guess : 2579 |
|||
Your score for this guess: Bulls = 3 Cows = 0 |
|||
Enter your guess : 2589 |
|||
Your score for this guess: Bulls = 3 Cows = 0 |
|||
Enter your guess : 2539 |
|||
Your score for this guess: Bulls = 3 Cows = 0 |
|||
Enter your guess : 2549 |
|||
You've won with 9 valid guesses! |
|||
</pre> |
|||
=={{header|Lasso}}== |
|||
This game uses an HTML form to submit the answer. The random number and history are stored in a session using Lasso's built in session management. |
|||
<syntaxhighlight lang="lasso">[ |
|||
define randomizer() => { |
|||
local(n = string) |
|||
while(#n->size < 4) => { |
|||
local(r = integer_random(1,9)->asString) |
|||
#n !>> #r ? #n->append(#r) |
|||
} |
|||
return #n |
|||
} |
|||
define cowbullchecker(n::string,a::string) => { |
|||
integer(#n) == integer(#a) ? return (:true,map('cows'=0,'bulls'=4,'choice'=#a)) |
|||
local(cowbull = map('cows'=0,'bulls'=0,'choice'=#a),'checked' = array) |
|||
loop(4) => { |
|||
if(#checked !>> integer(#a->values->get(loop_count))) => { |
|||
#checked->insert(integer(#a->values->get(loop_count))) |
|||
if(integer(#n->values->get(loop_count)) == integer(#a->values->get(loop_count))) => { |
|||
#cowbull->find('bulls') += 1 |
|||
else(#n->values >> #a->values->get(loop_count)) |
|||
#cowbull->find('cows') += 1 |
|||
} |
|||
} |
|||
} |
|||
#cowbull->find('bulls') == 4 ? return (:true,map('cows'=0,'bulls'=4,'choice'=#a)) |
|||
return (:true,#cowbull) |
|||
} |
|||
session_start('user') |
|||
session_addvar('user', 'num') |
|||
session_addvar('user', 'historic_choices') |
|||
// set up rand |
|||
var(num)->isNotA(::string) ? var(num = randomizer) |
|||
var(historic_choices)->isNotA(::array) ? var(historic_choices = array) |
|||
local(success = false) |
|||
// check answer |
|||
if(web_request->param('a')->asString->size) => { |
|||
local(success,result) = cowbullchecker($num,web_request->param('a')->asString) |
|||
$historic_choices->insert(#result) |
|||
} |
|||
if(web_request->params->asStaticArray >> 'restart') => { |
|||
$num = randomizer |
|||
$historic_choices = array |
|||
} |
|||
] |
|||
<h1>Bulls and Cows</h1> |
|||
<p>Guess the 4-digit number...</p> |
|||
<p>Your win if the guess is the same as the randomly chosen number.<br> |
|||
- A score of one bull is accumulated for each digit in your guess that equals the corresponding digit in the randomly chosen initial number.<br> |
|||
- A score of one cow is accumulated for each digit in your guess that also appears in the randomly chosen number, but in the wrong position. |
|||
</p> |
|||
[ |
|||
local(win = false) |
|||
if($historic_choices->size) => { |
|||
with c in $historic_choices do => {^ |
|||
'<p>'+#c->find('choice')+': Bulls: '+#c->find('bulls')+', Cows: '+#c->find('cows') |
|||
if(#c->find('bulls') == 4) => {^ |
|||
' - YOU WIN!' |
|||
#win = true |
|||
^} |
|||
'</p>' |
|||
^} |
|||
} |
|||
if(not #win) => {^ |
|||
] |
|||
<form action="?" method="post"> |
|||
<input name="a" value="[web_request->param('a')->asString]" size="5"> |
|||
<input type="submit" name="guess"> |
|||
<a href="?restart">Restart</a> |
|||
</form> |
|||
[else |
|||
'<a href="?restart">Restart</a>' |
|||
^}] |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
Game in progress: |
|||
<pre>Bulls and Cows |
|||
Guess the 4-digit number... |
|||
Your win if the guess is the same as the randomly chosen number. |
|||
- A score of one bull is accumulated for each digit in your guess that equals the corresponding digit in the randomly chosen initial number. |
|||
- A score of one cow is accumulated for each digit in your guess that also appears in the randomly chosen number, but in the wrong position. |
|||
4567: Bulls: 0, Cows: 1 |
|||
4567: Bulls: 0, Cows: 1 |
|||
(input box) (submit button) Restart</pre> |
|||
{{out}} |
|||
Game in to completion: |
|||
<pre>Bulls and Cows |
|||
Guess the 4-digit number... |
|||
Your win if the guess is the same as the randomly chosen number. |
|||
- A score of one bull is accumulated for each digit in your guess that equals the corresponding digit in the randomly chosen initial number. |
|||
- A score of one cow is accumulated for each digit in your guess that also appears in the randomly chosen number, but in the wrong position. |
|||
1234: Bulls: 0, Cows: 2 |
|||
1256: Bulls: 0, Cows: 1 |
|||
1789: Bulls: 0, Cows: 1 |
|||
1222: Bulls: 0, Cows: 0 |
|||
3456: Bulls: 1, Cows: 2 |
|||
3564: Bulls: 0, Cows: 3 |
|||
3567: Bulls: 0, Cows: 2 |
|||
8564: Bulls: 0, Cows: 2 |
|||
3564: Bulls: 0, Cows: 3 |
|||
4365: Bulls: 0, Cows: 3 |
|||
5436: Bulls: 2, Cows: 1 |
|||
5478: Bulls: 2, Cows: 0 |
|||
5463: Bulls: 3, Cows: 0 |
|||
5468: Bulls: 2, Cows: 0 |
|||
5493: Bulls: 4, Cows: 0 - YOU WIN! |
|||
Restart</pre> |
|||
=={{header|Liberty BASIC}}== |
|||
<syntaxhighlight lang="lb"> |
|||
do while len( secret$) <4 |
|||
c$ =chr$( int( rnd( 1) *9) +49) |
|||
if not( instr( secret$, c$)) then secret$ =secret$ +c$ |
|||
loop |
|||
print " Secret number has been guessed.... "; secret$ |
|||
guesses = 0 |
|||
[loop] |
|||
print " Your guess "; |
|||
input " "; guess$ |
|||
guesses = guesses +1 |
|||
r$ =score$( guess$, secret$) |
|||
bulls =val( word$( r$, 1, ",")) |
|||
cows =val( word$( r$, 2, ",")) |
|||
print " Result: "; bulls; " bulls, and "; cows; " cows" |
|||
print |
|||
if guess$ =secret$ then |
|||
print " You won after "; guesses; " guesses!" |
|||
print " You guessed it in "; guesses |
|||
print " Thanks for playing!" |
|||
wait |
|||
end if |
|||
goto [loop] |
|||
end ' _____________________________________________________________ |
|||
function check( i$) ' check =0 if no digit repeats, else =1 |
|||
check =0 |
|||
for i =1 to 3 |
|||
for j =i +1 to 4 |
|||
if mid$( i$, i, 1) =mid$( i$, j, 1) then check =1 |
|||
next j |
|||
next i |
|||
end function |
|||
function score$( a$, b$) ' return as a csv string the number of bulls & cows. |
|||
bulls = 0: cows = 0 |
|||
for i = 1 to 4 |
|||
c$ = mid$( a$, i, 1) |
|||
if mid$( b$, i, 1) = c$ then |
|||
bulls = bulls + 1 |
|||
else |
|||
if instr( b$, c$) <>0 and instr( b$, c$) <>i then |
|||
cows = cows + 1 |
|||
end if |
|||
end if |
|||
next i |
|||
score$ =str$( bulls); ","; str$( cows) |
|||
end function |
|||
[quit] |
|||
close #w |
|||
end |
|||
</syntaxhighlight> |
|||
=={{header|Logo}}== |
|||
{{works with|UCB Logo}} |
|||
<syntaxhighlight lang="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</syntaxhighlight> |
|||
=={{header|Lua}}== |
|||
<syntaxhighlight lang="lua">function ShuffleArray(array) |
|||
for i=1,#array-1 do |
|||
local t = math.random(i, #array) |
|||
array[i], array[t] = array[t], array[i] |
|||
end |
|||
end |
|||
function GenerateNumber() |
|||
local digits = {1,2,3,4,5,6,7,8,9} |
|||
ShuffleArray(digits) |
|||
return digits[1] * 1000 + |
|||
digits[2] * 100 + |
|||
digits[3] * 10 + |
|||
digits[4] |
|||
end |
|||
function IsMalformed(input) |
|||
local malformed = false |
|||
if #input == 4 then |
|||
local already_used = {} |
|||
for i=1,4 do |
|||
local digit = input:byte(i) - string.byte('0') |
|||
if digit < 1 or digit > 9 or already_used[digit] then |
|||
malformed = true |
|||
break |
|||
end |
|||
already_used[digit] = true |
|||
end |
|||
else |
|||
malformed = true |
|||
end |
|||
return malformed |
|||
end |
|||
math.randomseed(os.time()) |
|||
math.randomseed(math.random(2^31-1)) -- since os.time() only returns seconds |
|||
print("\nWelcome to Bulls and Cows!") |
|||
print("") |
|||
print("The object of this game is to guess the random 4-digit number that the") |
|||
print("computer has chosen. The number is generated using only the digits 1-9,") |
|||
print("with no repeated digits. Each time you enter a guess, you will score one") |
|||
print("\"bull\" for each digit in your guess that matches the corresponding digit") |
|||
print("in the computer-generated number, and you will score one \"cow\" for each") |
|||
print("digit in your guess that appears in the computer-generated number, but is") |
|||
print("in the wrong position. Use this information to refine your guesses. When") |
|||
print("you guess the correct number, you win."); |
|||
print("") |
|||
quit = false |
|||
repeat |
|||
magic_number = GenerateNumber() |
|||
magic_string = tostring(magic_number) -- Easier to do scoring with a string |
|||
repeat |
|||
io.write("\nEnter your guess (or 'Q' to quit): ") |
|||
user_input = io.read() |
|||
if user_input == 'Q' or user_input == 'q' then |
|||
quit = true |
|||
break |
|||
end |
|||
if not IsMalformed(user_input) then |
|||
if user_input == magic_string then |
|||
print("YOU WIN!!!") |
|||
else |
|||
local bulls, cows = 0, 0 |
|||
for i=1,#user_input do |
|||
local find_result = magic_string:find(user_input:sub(i,i)) |
|||
if find_result and find_result == i then |
|||
bulls = bulls + 1 |
|||
elseif find_result then |
|||
cows = cows + 1 |
|||
end |
|||
end |
|||
print(string.format("You scored %d bulls, %d cows", bulls, cows)) |
|||
end |
|||
else |
|||
print("Malformed input. You must enter a 4-digit number with") |
|||
print("no repeated digits, using only the digits 1-9.") |
|||
end |
|||
until user_input == magic_string |
|||
if not quit then |
|||
io.write("\nPress <Enter> to play again or 'Q' to quit: ") |
|||
user_input = io.read() |
|||
if user_input == 'Q' or user_input == 'q' then |
|||
quit = true |
|||
end |
|||
end |
|||
if quit then |
|||
print("\nGoodbye!") |
|||
end |
|||
until quit</syntaxhighlight> |
|||
Another version: |
|||
<syntaxhighlight lang="lua">function createNewNumber () |
|||
math.randomseed(os.time()) |
|||
local numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9} |
|||
local tNumb = {} -- list of numbers |
|||
for i = 1, 4 do |
|||
table.insert(tNumb, math.random(#tNumb+1), table.remove(numbers, math.random(#numbers))) |
|||
end |
|||
return tNumb |
|||
end |
|||
TNumber = createNewNumber () |
|||
print ('(right number: ' .. table.concat (TNumber) .. ')') |
|||
function isValueInList (value, list) |
|||
for i, v in ipairs (list) do |
|||
if v == value then return true end |
|||
end |
|||
return false |
|||
end |
|||
local nGuesses = 0 |
|||
while not GameOver do |
|||
nGuesses = nGuesses + 1 |
|||
print("Enter your guess (or 'q' to quit): ") |
|||
local input |
|||
while not input do |
|||
input = io.read() |
|||
end |
|||
if input == "q" then |
|||
GameOver = true |
|||
return |
|||
end |
|||
local tInput = {} |
|||
for i=1, string.len(input) do |
|||
local number = tonumber(string.sub(input,i,i)) |
|||
if number and not isValueInList (number, tInput) then |
|||
table.insert (tInput, number) |
|||
end |
|||
end |
|||
local malformed = false |
|||
if not (string.len(input) == 4) or not (#tInput == 4) then |
|||
print (nGuesses, 'bad input: too short or too long') |
|||
malformed = true |
|||
end |
|||
if not malformed then |
|||
print (nGuesses, 'parsed input:', table.concat(tInput, ', ')) |
|||
local nBulls, nCows = 0, 0 |
|||
for i, number in ipairs (tInput) do |
|||
if TNumber[i] == number then |
|||
nBulls = nBulls + 1 |
|||
elseif isValueInList (number, TNumber) then |
|||
nCows = nCows + 1 |
|||
end |
|||
end |
|||
print (nGuesses, 'Bulls: '.. nBulls .. ' Cows: ' .. nCows) |
|||
if nBulls == 4 then |
|||
print (nGuesses, 'Win!') |
|||
GameOver = true |
|||
end |
|||
end |
|||
end</syntaxhighlight> |
|||
=={{header|M2000 Interpreter}}== |
|||
<syntaxhighlight lang="m2000 interpreter"> |
|||
Module Game { |
|||
Malformed=lambda (a$)->{ |
|||
=true |
|||
if len(a$)<>4 then exit |
|||
n=0 : dummy=val(a$,"int",n) |
|||
if n<>5 or dummy=0 then exit |
|||
for i=1 to 9 |
|||
if len(filter$(a$,str$(i,0)))<3 then break |
|||
next i |
|||
=false |
|||
} |
|||
BullsAndCows$=lambda$ (a$, b$, &ok) ->{ |
|||
Def b, c |
|||
for i=1 to 4 |
|||
if mid$(a$,i,1)=mid$(b$,i,1) then |
|||
b++ |
|||
else.if instr(b$,mid$(a$,i,1))>0 then |
|||
c++ |
|||
end if |
|||
next i |
|||
ok=b=4 |
|||
=format$("bulls {0}, cows {1}", b, c) |
|||
} |
|||
Random$=lambda$ ->{ |
|||
def repl$, bank$, c$ |
|||
bank$="123456789" |
|||
for i=1 to 4 |
|||
c$=mid$(bank$,random(1,len(bank$)),1) |
|||
bank$=filter$(bank$, c$) |
|||
repl$+=c$ |
|||
next i |
|||
=repl$ |
|||
} |
|||
target$=Random$() |
|||
def boolean win=false, a$ |
|||
do |
|||
do |
|||
Input "Next guess ";a% |
|||
a$=str$(a%,0) |
|||
if Malformed(a$) then Print "Malformed input, try again" else exit |
|||
always |
|||
Print BullsAndCows$(a$, target$, &win) |
|||
if win then exit |
|||
Print "Bad guess! (4 unique digits, 1-9)" |
|||
always |
|||
Print "You guess it" |
|||
} |
|||
Game |
|||
</syntaxhighlight> |
|||
=={{header|Maple}}== |
|||
<syntaxhighlight lang="maple">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:</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Please enter a 4 digit integer with no repeating digits |
|||
Guess 1: [1, 2, 3, 4] |
|||
1 Cow, 1 Bull. |
|||
Please enter a 4 digit integer with no repeating digits |
|||
Guess 2: [2, 3, 4, 5] |
|||
0 Cows, 1 Bull. |
|||
... |
|||
</pre> |
|||
=={{header|Mathematica}}/{{header|Wolfram Language}}== |
|||
<syntaxhighlight lang="mathematica">digits=Last@FixedPointList[If[Length@Union@#==4,#,Table[Random[Integer,{1,9}],{4}]]&,{}] |
|||
codes=ToCharacterCode[StringJoin[ToString/@digits]]; |
|||
Module[{r,bulls,cows}, |
|||
While[True, |
|||
r=InputString[]; |
|||
If[r===$Canceled,Break[], |
|||
With[{userCodes=ToCharacterCode@r}, |
|||
If[userCodes===codes,Print[r<>": You got it!"];Break[], |
|||
If[Length@userCodes==Length@codes, |
|||
bulls=Count[userCodes-codes,0];cows=Length@Intersection[codes,userCodes]-bulls; |
|||
Print[r<>": "<>ToString[bulls]<>"bull(s), "<>ToString@cows<>"cow(s)."], |
|||
Print["Guess four digits."]]]]]]]</syntaxhighlight> |
|||
Output: |
|||
<pre>{8, 2, 6, 1} |
|||
3432: 0 bull(s), 1 cow(s). |
|||
Illegal input. |
|||
8261: You got it!</pre> |
|||
=={{header|MATLAB}}== |
|||
<syntaxhighlight lang="matlab">function BullsAndCows |
|||
% Plays the game Bulls and Cows as the "game master" |
|||
% Create a secret number |
|||
nDigits = 4; |
|||
lowVal = 1; |
|||
highVal = 9; |
|||
digitList = lowVal:highVal; |
|||
secret = zeros(1, 4); |
|||
for k = 1:nDigits |
|||
idx = randi(length(digitList)); |
|||
secret(k) = digitList(idx); |
|||
digitList(idx) = []; |
|||
end |
|||
% Give game information |
|||
fprintf('Welcome to Bulls and Cows!\n') |
|||
fprintf('Try to guess the %d-digit number (no repeated digits).\n', nDigits) |
|||
fprintf('Digits are between %d and %d (inclusive).\n', lowVal, highVal) |
|||
fprintf('Score: 1 Bull per correct digit in correct place.\n') |
|||
fprintf(' 1 Cow per correct digit in incorrect place.\n') |
|||
fprintf('The number has been chosen. Now it''s your moooooove!\n') |
|||
gs = input('Guess: ', 's'); |
|||
% Loop until user guesses right or quits (no guess) |
|||
nGuesses = 1; |
|||
while gs |
|||
gn = str2double(gs); |
|||
if isnan(gn) || length(gn) > 1 % Not a scalar |
|||
fprintf('Malformed guess. Keep to valid scalars.\n') |
|||
gs = input('Try again: ', 's'); |
|||
else |
|||
g = sprintf('%d', gn) - '0'; |
|||
if length(g) ~= nDigits || any(g < lowVal) || any(g > highVal) || ... |
|||
length(unique(g)) ~= nDigits % Invalid number for game |
|||
fprintf('Malformed guess. Remember:\n') |
|||
fprintf(' %d digits\n', nDigits) |
|||
fprintf(' Between %d and %d inclusive\n', lowVal, highVal) |
|||
fprintf(' No repeated digits\n') |
|||
gs = input('Try again: ', 's'); |
|||
else |
|||
score = CountBullsCows(g, secret); |
|||
if score(1) == nDigits |
|||
fprintf('You win! Bully for you! Only %d guesses.\n', nGuesses) |
|||
gs = ''; |
|||
else |
|||
fprintf('Score: %d Bulls, %d Cows\n', score) |
|||
gs = input('Guess: ', 's'); |
|||
end |
|||
end |
|||
end |
|||
nGuesses = nGuesses+1; % Counts malformed guesses |
|||
end |
|||
end |
|||
function score = CountBullsCows(guess, correct) |
|||
% Checks the guessed array of digits against the correct array to find the score |
|||
% Assumes arrays of same length and valid numbers |
|||
bulls = guess == correct; |
|||
cows = ismember(guess(~bulls), correct); |
|||
score = [sum(bulls) sum(cows)]; |
|||
end</syntaxhighlight> |
|||
{{out}} |
|||
<pre>Welcome to Bulls and Cows! |
|||
Try to guess the 4-digit number (no repeated digits). |
|||
Digits are between 1 and 9 (inclusive). |
|||
Score: 1 Bull per correct digit in correct place. |
|||
1 Cow per correct digit in incorrect place. |
|||
The number has been chosen. Now it's your moooooove! |
|||
Guess: 1234 |
|||
Score: 0 Bulls, 2 Cows |
|||
Guess: 2156 |
|||
Score: 0 Bulls, 1 Cows |
|||
Guess: 7819 |
|||
Score: 0 Bulls, 1 Cows |
|||
Guess: 3457 |
|||
Score: 0 Bulls, 2 Cows |
|||
Guess: hello |
|||
Malformed guess. Keep to valid scalars. |
|||
Try again: 1123 |
|||
Malformed guess. Remember: |
|||
4 digits |
|||
Between 1 and 9 inclusive |
|||
No repeated digits |
|||
Try again: 34567 |
|||
Malformed guess. Remember: |
|||
4 digits |
|||
Between 1 and 9 inclusive |
|||
No repeated digits |
|||
Try again: 4368 |
|||
You win! Bully for you! Only 8 guesses.</pre> |
|||
=={{header|MAXScript}}== |
|||
<syntaxhighlight lang="maxscript"> |
|||
numCount = 4 -- number of digits to use |
|||
digits = #(1, 2, 3, 4, 5, 6, 7, 8, 9) |
|||
num = "" |
|||
while num.count < numCount and digits.count > 0 do |
|||
( |
|||
local r = random 1 digits.count |
|||
append num (digits[r] as string) |
|||
deleteitem digits r |
|||
) |
|||
digits = undefined |
|||
numGuesses = 0 |
|||
inf = "Rules: \n1. Choose only % unique digits in any combination"+\ |
|||
" (0 can't be used).\n2. Only positive integers are allowed."+\ |
|||
"\n3. For each digit that is in it's place, you get a bull,\n"+\ |
|||
"\tand for each digit that is not in it's place, you get a cow."+\ |
|||
"\n4. The game is won when your number matches the number I chose."+\ |
|||
"\n\nPress [esc] to quit the game.\n\n" |
|||
clearlistener() |
|||
format inf num.count |
|||
while not keyboard.escpressed do |
|||
( |
|||
local userVal = getkbvalue prompt:"\nEnter your number: " |
|||
if (userVal as string) == num do |
|||
( |
|||
format "\nCorrect! The number is %. It took you % moves.\n" num numGuesses |
|||
exit with OK |
|||
) |
|||
local bulls = 0 |
|||
local cows = 0 |
|||
local badInput = false |
|||
case of |
|||
( |
|||
(classof userVal != integer): |
|||
( |
|||
format "\nThe number must be a positive integer.\n" |
|||
badInput = true |
|||
) |
|||
((userVal as string).count != num.count): |
|||
( |
|||
format "\nThe number must have % digits.\n" num.count |
|||
badInput = true |
|||
) |
|||
((makeuniquearray (for i in 1 to (userVal as string).count \ |
|||
collect (userVal as string)[i])).count != (userVal as string).count): |
|||
( |
|||
format "\nThe number can only have unique digits.\n" |
|||
badInput = true |
|||
) |
|||
) |
|||
if not badInput do |
|||
( |
|||
userVal = userVal as string |
|||
i = 1 |
|||
while i <= userVal.count do |
|||
( |
|||
for j = 1 to num.count do |
|||
( |
|||
if userVal[i] == num[j] do |
|||
( |
|||
if i == j then bulls += 1 else cows += 1 |
|||
) |
|||
) |
|||
i += 1 |
|||
) |
|||
numGuesses += 1 |
|||
format "\nBulls: % Cows: %\n" bulls cows |
|||
) |
|||
)</syntaxhighlight> |
|||
{{out}} |
|||
<syntaxhighlight lang="text"> |
|||
OK |
|||
Rules: |
|||
1. Choose only 4 unique digits in any combination (0 can't be used). |
|||
2. Only positive integers are allowed. |
|||
3. For each digit that is in it's place, you get a bull, |
|||
and for each digit that is not in it's place, you get a cow. |
|||
4. The game is won when your number matches the number I chose. |
|||
Press [esc] to quit the game. |
|||
OK |
|||
Enter your number: 2468 |
|||
Bulls: 0 Cows: 2 |
|||
Enter your number: 2448 |
|||
The number can only have unique digits. |
|||
Enter your number: 1357 |
|||
Bulls: 0 Cows: 1 |
|||
</syntaxhighlight> |
|||
=={{header|MiniScript}}== |
|||
<syntaxhighlight lang="miniscript">secret = range(1,9) |
|||
secret.shuffle |
|||
secret = secret[:4].join("") |
|||
while true |
|||
guess = input("Your guess? ").split("") |
|||
if guess.len != 4 then |
|||
print "Please enter 4 numbers, with no spaces." |
|||
continue |
|||
end if |
|||
bulls = 0 |
|||
cows = 0 |
|||
for i in guess.indexes |
|||
if secret[i] == guess[i] then |
|||
bulls = bulls + 1 |
|||
else if secret.indexOf(guess[i]) != null then |
|||
cows = cows + 1 |
|||
end if |
|||
end for |
|||
if bulls == 4 then |
|||
print "You got it! Great job!" |
|||
break |
|||
end if |
|||
print "You score " + bulls + " bull" + "s"*(bulls!=1) + |
|||
" and " + cows + " cow" + "s"*(cows!=1) + "." |
|||
end while</syntaxhighlight> |
|||
{{out}} |
|||
<pre>Your guess? 2385 |
|||
You score 0 bulls and 2 cows. |
|||
Your guess? 2323 |
|||
You score 0 bulls and 2 cows. |
|||
Your guess? 2211 |
|||
You score 2 bulls and 1 cow. |
|||
... |
|||
Your guess? 8542 |
|||
You score 3 bulls and 0 cows. |
|||
Your guess? 8642 |
|||
You got it! Great job!</pre> |
|||
=={{header|MUMPS}}== |
|||
<syntaxhighlight lang="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.</syntaxhighlight> |
|||
=={{header|Nanoquery}}== |
|||
{{trans|Python}} |
|||
<syntaxhighlight lang="nanoquery">import Nanoquery.Util; random = new(Random) |
|||
// a function to verify the user's input |
|||
def verify_digits(input) |
|||
global size |
|||
seen = "" |
|||
if len(input) != size |
|||
return false |
|||
else |
|||
for char in input |
|||
if not char in "0123456789" |
|||
return false |
|||
else if char in seen |
|||
return false |
|||
end |
|||
seen += char |
|||
end |
|||
end |
|||
return true |
|||
end |
|||
size = 4 |
|||
chosen = "" |
|||
while len(chosen) < size |
|||
digit = random.getInt(8) + 1 |
|||
if not str(digit) in chosen |
|||
chosen += str(digit) |
|||
end |
|||
end |
|||
println "I have chosen a number from 4 unique digits from 1 to 9 arranged in a random order." |
|||
println "You need to input a 4 digit, unique digit number as a guess at what I have chosen." |
|||
guesses = 1 |
|||
won = false |
|||
while !won |
|||
print "\nNext guess [" + str(guesses) + "]: " |
|||
guess = input() |
|||
if !verify_digits(guess) |
|||
println "Problem, try again. You need to enter 4 unique digits from 1 to 9" |
|||
else |
|||
if guess = chosen |
|||
won = true |
|||
else |
|||
bulls = 0 |
|||
cows = 0 |
|||
for i in range(0, size - 1) |
|||
if guess[i] = chosen[i] |
|||
bulls += 1 |
|||
else if guess[i] in chosen |
|||
cows += 1 |
|||
end |
|||
end |
|||
println format(" %d Bulls\n %d Cows", bulls, cows) |
|||
guesses += 1 |
|||
end |
|||
end |
|||
end |
|||
println "\nCongratulations you guess correctly in " + guesses + " attempts"</syntaxhighlight> |
|||
{{out}} |
|||
<pre>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]: 1234 |
|||
1 Bulls |
|||
2 Cows |
|||
Next guess [2]: 1324 |
|||
0 Bulls |
|||
3 Cows |
|||
... |
|||
Next guess [10]: 2534 |
|||
2 Bulls |
|||
2 Cows |
|||
Next guess [11]: 4532 |
|||
Congratulations you guess correctly in 11 attempts</pre> |
|||
=={{header|Nim}}== |
|||
{{trans|Python}} |
|||
<syntaxhighlight lang="nim">import random, strutils, strformat, sequtils |
|||
randomize() |
|||
const |
|||
Digits = "123456789" |
|||
DigitSet = {Digits[0]..Digits[^1]} |
|||
Size = 4 |
|||
proc sample(s: string; n: Positive): string = |
|||
## Return a random sample of "n" characters extracted from string "s". |
|||
var s = s |
|||
s.shuffle() |
|||
result = s[0..<n] |
|||
proc plural(n: int): string = |
|||
if n > 1: "s" else: "" |
|||
let chosen = Digits.sample(Size) |
|||
echo &"I have chosen a number from {Size} unique digits from 1 to 9 arranged in a random order." |
|||
echo &"You need to input a {Size} digit, unique digit number as a guess at what I have chosen." |
|||
var guesses = 0 |
|||
while true: |
|||
inc guesses |
|||
var guess = "" |
|||
while true: |
|||
stdout.write(&"\nNext guess {guesses}: ") |
|||
guess = stdin.readLine().strip() |
|||
if guess.len == Size and allCharsInSet(guess, DigitSet) and guess.deduplicate.len == Size: |
|||
break |
|||
echo &"Problem, try again. You need to enter {Size} unique digits from 1 to 9." |
|||
if guess == chosen: |
|||
echo &"\nCongratulations! You guessed correctly in {guesses} attempts." |
|||
break |
|||
var bulls, cows = 0 |
|||
for i in 0..<Size: |
|||
if guess[i] == chosen[i]: inc bulls |
|||
elif guess[i] in chosen: inc cows |
|||
echo &" {bulls} Bull{plural(bulls)}\n {cows} Cow{plural(cows)}"</syntaxhighlight> |
|||
{{out}} |
|||
Sample output: |
|||
<pre>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: 1234 |
|||
2 Bulls |
|||
0 Cow |
|||
Next guess 2: 1256 |
|||
1 Bull |
|||
0 Cow |
|||
Next guess 3: 2378 |
|||
1 Bull |
|||
3 Cows |
|||
Next guess 4: 7238 |
|||
Congratulations! You guessed correctly in 4 attempts.</pre> |
|||
=={{header|OCaml}}== |
=={{header|OCaml}}== |
||
< |
<syntaxhighlight lang="ocaml">let rec input () = |
||
let s = read_line () in |
let s = read_line () in |
||
try |
try |
||
Line 910: | Line 5,270: | ||
with Exit -> |
with Exit -> |
||
prerr_endline "That is an invalid entry. Please try again."; |
prerr_endline "That is an invalid entry. Please try again."; |
||
input() |
input () |
||
;; |
;; |
||
Line 917: | Line 5,277: | ||
List.iter2 (fun x y -> |
List.iter2 (fun x y -> |
||
if x = y then incr bull |
if x = y then incr bull |
||
) g t; |
|||
let cow = ref 0 in |
let cow = ref 0 in |
||
List.iter (fun x -> |
List.iter (fun x -> |
||
if List.mem x t then incr cow |
if List.mem x t then incr cow |
||
) g; |
|||
cow := !cow - !bull; |
cow := !cow - !bull; |
||
Printf.printf "%d bulls, %d cows\n%!" !bull !cow |
Printf.printf "%d bulls, %d cows\n%!" !bull !cow |
||
Line 927: | Line 5,287: | ||
let () = |
let () = |
||
Random.self_init(); |
Random.self_init (); |
||
let rec mkgoal acc = function 4 -> acc |
let rec mkgoal acc = function 4 -> acc |
||
| i -> |
| i -> |
||
Line 938: | Line 5,298: | ||
let found = ref false in |
let found = ref false in |
||
while not !found do |
while not !found do |
||
let t = input() in |
let t = input () in |
||
if t = g |
if t = g |
||
then found := true |
then found := true |
||
Line 944: | Line 5,304: | ||
done; |
done; |
||
print_endline "Congratulations you guessed correctly"; |
print_endline "Congratulations you guessed correctly"; |
||
;;</syntaxhighlight> |
|||
;; |
|||
=={{header|Oforth}}== |
|||
</lang> |
|||
<syntaxhighlight lang="oforth">: bullsAndCows |
|||
| numbers guess digits bulls cows | |
|||
ListBuffer new ->numbers |
|||
while(numbers size 4 <>) [ 9 rand dup numbers include ifFalse: [ numbers add ] else: [ drop ] ] |
|||
while(true) [ |
|||
"Enter a number of 4 different digits between 1 and 9 : " print |
|||
System.Console askln ->digits |
|||
digits asInteger isNull digits size 4 <> or ifTrue: [ "Number of four digits needed" println continue ] |
|||
digits map(#asDigit) ->guess |
|||
guess numbers zipWith(#==) occurrences(true) ->bulls |
|||
bulls 4 == ifTrue: [ "You won !" println return ] |
|||
guess filter(#[numbers include]) size bulls - ->cows |
|||
System.Out "Bulls = " << bulls << ", cows = " << cows << cr |
|||
] ;</syntaxhighlight> |
|||
=={{header|ooRexx}}== |
|||
The solution at [[#Version_2|Rexx Version 2]] is a valid ooRexx program. |
|||
=={{header|Oz}}== |
|||
<syntaxhighlight lang="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}</syntaxhighlight> |
|||
=={{header|PARI/GP}}== |
|||
This simple implementation expects guesses in the form [a,b,c,d]. |
|||
<syntaxhighlight lang="parigp">bc()={ |
|||
my(u,v,bulls,cows); |
|||
while(#vecsort(v=vector(4,i,random(9)+1),,8)<4,); |
|||
while(bulls<4, |
|||
u=input(); |
|||
if(type(u)!="t_VEC"|#u!=4,next); |
|||
bulls=sum(i=1,4,u[i]==v[i]); |
|||
cows=sum(i=1,4,sum(j=1,4,i!=j&v[i]==u[j])); |
|||
print("You have "bulls" bulls and "cows" cows") |
|||
) |
|||
};</syntaxhighlight> |
|||
=={{header|Pascal}}== |
|||
<syntaxhighlight lang="pascal">Program BullCow; |
|||
{$mode objFPC} |
|||
uses Math, SysUtils; |
|||
type |
|||
TFourDigit = array[1..4] of integer; |
|||
Procedure WriteFourDigit(fd: TFourDigit); |
|||
{ Write out a TFourDigit with no line break following. } |
|||
var |
|||
i: integer; |
|||
begin |
|||
for i := 1 to 4 do |
|||
begin |
|||
Write(fd[i]); |
|||
end; |
|||
end; |
|||
Function WellFormed(Tentative: TFourDigit): Boolean; |
|||
{ Does the TFourDigit avoid repeating digits? } |
|||
var |
|||
current, check: integer; |
|||
begin |
|||
Result := True; |
|||
for current := 1 to 4 do |
|||
begin |
|||
for check := current + 1 to 4 do |
|||
begin |
|||
if Tentative[check] = Tentative[current] then |
|||
begin |
|||
Result := False; |
|||
end; |
|||
end; |
|||
end; |
|||
end; |
|||
Function MakeNumber(): TFourDigit; |
|||
{ Make a random TFourDigit, keeping trying until it is well-formed. } |
|||
var |
|||
i: integer; |
|||
begin |
|||
for i := 1 to 4 do |
|||
begin |
|||
Result[i] := RandomRange(1, 9); |
|||
end; |
|||
if not WellFormed(Result) then |
|||
begin |
|||
Result := MakeNumber(); |
|||
end; |
|||
end; |
|||
Function StrToFourDigit(s: string): TFourDigit; |
|||
{ Convert an (input) string to a TFourDigit. } |
|||
var |
|||
i: integer; |
|||
begin |
|||
for i := 1 to Length(s) do |
|||
begin |
|||
StrToFourDigit[i] := StrToInt(s[i]); |
|||
end; |
|||
end; |
|||
Function Wins(Num, Guess: TFourDigit): Boolean; |
|||
{ Does the guess win? } |
|||
var |
|||
i: integer; |
|||
begin |
|||
Result := True; |
|||
for i := 1 to 4 do |
|||
begin |
|||
if Num[i] <> Guess[i] then |
|||
begin |
|||
Result := False; |
|||
Exit; |
|||
end; |
|||
end; |
|||
end; |
|||
Function GuessScore(Num, Guess: TFourDigit): string; |
|||
{ Represent the score of the current guess as a string. } |
|||
var |
|||
i, j, bulls, cows: integer; |
|||
begin |
|||
bulls := 0; |
|||
cows := 0; |
|||
{ Count the cows and bulls. } |
|||
for i := 1 to 4 do |
|||
begin |
|||
for j := 1 to 4 do |
|||
begin |
|||
if (Num[i] = Guess[j]) then |
|||
begin |
|||
{ If the indices are the same, that would be a bull. } |
|||
if (i = j) then |
|||
begin |
|||
bulls := bulls + 1; |
|||
end |
|||
else |
|||
begin |
|||
cows := cows + 1; |
|||
end; |
|||
end; |
|||
end; |
|||
end; |
|||
{ Format the result as a sentence. } |
|||
Result := IntToStr(bulls) + ' bulls, ' + IntToStr(cows) + ' cows.'; |
|||
end; |
|||
Function GetGuess(): TFourDigit; |
|||
{ Get a well-formed user-supplied TFourDigit guess. } |
|||
var |
|||
input: string; |
|||
begin |
|||
WriteLn('Enter a guess:'); |
|||
ReadLn(input); |
|||
{ Must be 4 digits. } |
|||
if Length(input) = 4 then |
|||
begin |
|||
Result := StrToFourDigit(input); |
|||
if not WellFormed(Result) then |
|||
begin |
|||
WriteLn('Four unique digits, please.'); |
|||
Result := GetGuess(); |
|||
end; |
|||
end |
|||
else |
|||
begin |
|||
WriteLn('Please guess a four-digit number.'); |
|||
Result := GetGuess(); |
|||
end; |
|||
end; |
|||
var |
|||
Num, Guess: TFourDigit; |
|||
Turns: integer; |
|||
begin |
|||
{ Initialize the randymnity. } |
|||
Randomize(); |
|||
{ Make the secred number. } |
|||
Num := MakeNumber(); |
|||
WriteLn('I have a secret number. Guess it!'); |
|||
Turns := 0; |
|||
{ Guess until the user gets it. } |
|||
While True do |
|||
begin |
|||
Guess := GetGuess(); |
|||
{ Count each guess as a turn. } |
|||
Turns := Turns + 1; |
|||
{ If the user won, tell them and ditch. } |
|||
if Wins(Num, Guess) then |
|||
begin |
|||
WriteLn('You won in ' + IntToStr(Turns) + ' tries.'); |
|||
Write('The number was '); |
|||
WriteFourDigit(Num); |
|||
WriteLn('!'); |
|||
Exit; |
|||
end |
|||
else { Otherwise, score it and get a new guess. } |
|||
begin |
|||
WriteLn(GuessScore(Num, Guess)); |
|||
end; |
|||
end; |
|||
end. |
|||
</syntaxhighlight> |
|||
=={{header|Perl}}== |
=={{header|Perl}}== |
||
< |
<syntaxhighlight lang="perl">use Data::Random qw(rand_set); |
||
use |
use List::MoreUtils qw(uniq); |
||
my $size = 4; |
my $size = 4; |
||
my $chosen = join |
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 |
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"; |
to input $size unique digits to guess my number\n"; |
||
my $guesses = |
for ( my $guesses = 1; ; $guesses++ ) { |
||
my $guess; |
my $guess; |
||
while(1) { |
while (1) { |
||
$guesses |
print "\nNext guess [$guesses]: "; |
||
$guess = <STDIN>; |
|||
while(1) { |
|||
chomp $guess; |
|||
$guess |
checkguess($guess) and last; |
||
print "$size digits, no repetition, no 0... retry\n"; |
|||
chomp $guess; |
|||
if ( !checkguess($guess) ) { |
|||
print "$size digits, no repetition, no 0... retry\n"; |
|||
} else { last; } |
|||
} |
} |
||
if ( $guess eq $chosen ) { |
if ( $guess eq $chosen ) { |
||
print "You did it in $guesses attempts!\n"; |
|||
last; |
|||
} else { |
|||
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"; |
|||
} |
} |
||
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 |
sub checkguess |
||
{ |
{ |
||
my $g = shift; |
my $g = shift; |
||
return uniq(split //, $g) == $size && $g =~ /^[1-9]{$size}$/; |
|||
my %h; |
|||
}</syntaxhighlight> |
|||
@h{ split(//, $g) } = (); |
|||
=={{header|Phix}}== |
|||
return keys %h == $size && $g =~ /^[1-9]{$size}$/; |
|||
<!--<syntaxhighlight lang="phix">(phixonline)--> |
|||
}</lang> |
|||
<span style="color: #000080;font-style:italic;">-- |
|||
-- demo\rosetta\BullsAndCows.exw |
|||
-- ============================= |
|||
--</span> |
|||
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span> <span style="color: #000080;font-style:italic;">-- (DEV lots of resizing issues)</span> |
|||
<span style="color: #008080;">constant</span> <span style="color: #000000;">N</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">4</span> |
|||
<span style="color: #008080;">function</span> <span style="color: #000000;">mask</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">ch</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">return</span> <span style="color: #7060A8;">power</span><span style="color: #0000FF;">(</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ch</span><span style="color: #0000FF;">-</span><span style="color: #008000;">'1'</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span> |
|||
<span style="color: #008080;">function</span> <span style="color: #000000;">score</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">guess</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">goal</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #004080;">integer</span> <span style="color: #000000;">bits</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">bulls</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">cows</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b</span> |
|||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">N</span> <span style="color: #008080;">do</span> |
|||
<span style="color: #000000;">b</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">goal</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> |
|||
<span style="color: #008080;">if</span> <span style="color: #000000;">guess</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]=</span><span style="color: #000000;">b</span> <span style="color: #008080;">then</span> |
|||
<span style="color: #000000;">bulls</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span> |
|||
<span style="color: #008080;">else</span> |
|||
<span style="color: #000000;">bits</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">mask</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">N</span> <span style="color: #008080;">do</span> |
|||
<span style="color: #000000;">b</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">mask</span><span style="color: #0000FF;">(</span><span style="color: #000000;">guess</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">])</span> |
|||
<span style="color: #008080;">if</span> <span style="color: #7060A8;">and_bits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">bits</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b</span><span style="color: #0000FF;">)!=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span> |
|||
<span style="color: #000000;">cows</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span> |
|||
<span style="color: #000000;">bits</span> <span style="color: #0000FF;">-=</span> <span style="color: #000000;">b</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span> |
|||
<span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">bulls</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">cows</span><span style="color: #0000FF;">}</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span> |
|||
<span style="color: #008080;">include</span> <span style="color: #000000;">pGUI</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span> |
|||
<span style="color: #004080;">Ihandle</span> <span style="color: #000000;">label</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">guess</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">res</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">dlg</span> |
|||
<span style="color: #004080;">string</span> <span style="color: #000000;">fmt</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">" Guess %-2d (%s) bulls:%d cows:%d\n"</span><span style="color: #0000FF;">,</span> |
|||
<span style="color: #000000;">tgt</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">shuffle</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"123456789"</span><span style="color: #0000FF;">)[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..</span><span style="color: #000000;">N</span><span style="color: #0000FF;">]</span> |
|||
<span style="color: #004080;">integer</span> <span style="color: #000000;">attempt</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span> |
|||
<span style="color: #008080;">function</span> <span style="color: #000000;">valuechanged_cb</span><span style="color: #0000FF;">(</span><span style="color: #004080;">Ihandle</span> <span style="color: #000080;font-style:italic;">/*guess*/</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #004080;">string</span> <span style="color: #000000;">g</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupGetAttribute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">guess</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"VALUE"</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">g</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">4</span> <span style="color: #008080;">and</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">unique</span><span style="color: #0000FF;">(</span><span style="color: #000000;">g</span><span style="color: #0000FF;">))=</span><span style="color: #000000;">4</span> <span style="color: #008080;">then</span> |
|||
<span style="color: #004080;">integer</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">bulls</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">cows</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">score</span><span style="color: #0000FF;">(</span><span style="color: #000000;">g</span><span style="color: #0000FF;">,</span><span style="color: #000000;">tgt</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #004080;">string</span> <span style="color: #000000;">title</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupGetAttribute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"TITLE"</span><span style="color: #0000FF;">)</span> <span style="color: #0000FF;">&</span> |
|||
<span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">fmt</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">attempt</span><span style="color: #0000FF;">,</span><span style="color: #000000;">g</span><span style="color: #0000FF;">,</span><span style="color: #000000;">bulls</span><span style="color: #0000FF;">,</span><span style="color: #000000;">cows</span><span style="color: #0000FF;">})</span> |
|||
<span style="color: #008080;">if</span> <span style="color: #000000;">bulls</span><span style="color: #0000FF;">=</span><span style="color: #000000;">N</span> <span style="color: #008080;">then</span> |
|||
<span style="color: #000000;">title</span> <span style="color: #0000FF;">&=</span> <span style="color: #008000;">"\nWell done!"</span> |
|||
<span style="color: #7060A8;">IupSetInt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">guess</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"ACTIVE"</span><span style="color: #0000FF;">,</span><span style="color: #004600;">false</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">else</span> |
|||
<span style="color: #7060A8;">IupSetAttribute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">guess</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"VALUE"</span><span style="color: #0000FF;">,</span><span style="color: #008000;">""</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
<span style="color: #7060A8;">IupSetStrAttribute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">res</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"TITLE"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">title</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #000000;">attempt</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span> |
|||
<span style="color: #7060A8;">IupSetAttribute</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dlg</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"SIZE"</span><span style="color: #0000FF;">,</span><span style="color: #004600;">NULL</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #7060A8;">IupRefresh</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dlg</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
<span style="color: #008080;">return</span> <span style="color: #004600;">IUP_DEFAULT</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span> |
|||
<span style="color: #008080;">procedure</span> <span style="color: #000000;">main</span><span style="color: #0000FF;">()</span> |
|||
<span style="color: #7060A8;">IupOpen</span><span style="color: #0000FF;">()</span> |
|||
<span style="color: #000000;">label</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupLabel</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Enter %d digits 1 to 9 without duplication"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">N</span><span style="color: #0000FF;">}))</span> |
|||
<span style="color: #000000;">guess</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupText</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"VALUECHANGED_CB"</span><span style="color: #0000FF;">,</span> <span style="color: #7060A8;">Icallback</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"valuechanged_cb"</span><span style="color: #0000FF;">))</span> |
|||
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupLabel</span><span style="color: #0000FF;">(</span><span style="color: #008000;">""</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #000000;">dlg</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">IupDialog</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">IupVbox</span><span style="color: #0000FF;">({</span><span style="color: #7060A8;">IupHbox</span><span style="color: #0000FF;">({</span><span style="color: #000000;">label</span><span style="color: #0000FF;">,</span><span style="color: #000000;">guess</span><span style="color: #0000FF;">},</span><span style="color: #008000;">"GAP=10,NORMALIZESIZE=VERTICAL"</span><span style="color: #0000FF;">),</span> |
|||
<span style="color: #7060A8;">IupHbox</span><span style="color: #0000FF;">({</span><span style="color: #000000;">res</span><span style="color: #0000FF;">})},</span><span style="color: #008000;">"MARGIN=5x5"</span><span style="color: #0000FF;">),</span><span style="color: #008000;">`TITLE="Bulls and Cows"`</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #7060A8;">IupShow</span><span style="color: #0000FF;">(</span><span style="color: #000000;">dlg</span><span style="color: #0000FF;">)</span> |
|||
<span style="color: #008080;">if</span> <span style="color: #7060A8;">platform</span><span style="color: #0000FF;">()!=</span><span style="color: #004600;">JS</span> <span style="color: #008080;">then</span> |
|||
<span style="color: #7060A8;">IupMainLoop</span><span style="color: #0000FF;">()</span> |
|||
<span style="color: #7060A8;">IupClose</span><span style="color: #0000FF;">()</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span> |
|||
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span> |
|||
<span style="color: #000000;">main</span><span style="color: #0000FF;">()</span> |
|||
<!--</syntaxhighlight>--> |
|||
{{out}} |
|||
<small>(as shown in the res label)</small> |
|||
<pre> |
|||
Guess 1 (5739) bulls:0 cows:3 |
|||
Guess 2 (7193) bulls:2 cows:1 |
|||
Guess 3 (3495) bulls:0 cows:2 |
|||
Guess 4 (7983) bulls:3 cows:0 |
|||
Guess 5 (7963) bulls:3 cows:0 |
|||
Guess 6 (7923) bulls:4 cows:0 |
|||
Well done! |
|||
</pre> |
|||
=={{header|PHP}}== |
=={{header|PHP}}== |
||
< |
<syntaxhighlight lang="php"><?php |
||
$size = 4; |
$size = 4; |
||
$ |
$chosen = implode(array_rand(array_flip(range(1,9)), $size)); |
||
foreach (array_rand($digits, $size) as $k) |
|||
$chosen .= $digits[$k]; |
|||
echo "I've chosen a number from $size unique digits from 1 to 9; you need |
echo "I've chosen a number from $size unique digits from 1 to 9; you need |
||
Line 1,037: | Line 5,769: | ||
preg_match("/^[1-9]{{$size}}$/", $g); |
preg_match("/^[1-9]{{$size}}$/", $g); |
||
} |
} |
||
?></ |
?></syntaxhighlight> |
||
=={{header|Picat}}== |
|||
{{trans|Python}} |
|||
<syntaxhighlight lang="picat">main => |
|||
Digits = to_array("123456789"), |
|||
Size = 4, |
|||
random_sample(Size,Size,[],ChosenIndecies), |
|||
Chosen = {Digits[I] : I in ChosenIndecies}, |
|||
printf("I have chosen a number from %d unique digits from 1 to 9 arranged in a random order.\n", Size), |
|||
printf("You need to input a %d digit, unique digit number as a guess at what I have chosen.\n", Size), |
|||
guess(Chosen,Size,1). |
|||
guess(Chosen,Size,NGuess) => |
|||
Input = read_line(), |
|||
Guess = Input.to_array(), |
|||
if len(Guess) != Size || len(sort_remove_dups(Input)) != Size || (member(D, Input), (D @< '1' || D @> '9')) then |
|||
printf("Problem, try again. You need to enter %d unique digits from 1 to 9\n", Size), |
|||
guess(Chosen,Size,NGuess) |
|||
elseif Guess == Chosen then |
|||
printf("\nCongratulations you guessed correctly in %d attempts\n", NGuess) |
|||
else |
|||
Bulls = sum([cond(Chosen[I] == Guess[I], 1, 0) : I in 1..Size]), |
|||
Cows = sum([cond(member(Chosen[I], Input), 1, 0) : I in 1..Size]), |
|||
printf("%d Bulls\n%d Cows\n", Bulls, Cows), |
|||
guess(Chosen, Size, NGuess+1) |
|||
end. |
|||
random_sample(_N,0,Chosen0,Chosen) => Chosen = Chosen0. |
|||
random_sample(N,I,Chosen0,Chosen) => |
|||
R = random() mod N + 1, |
|||
(not member(R, Chosen0) -> |
|||
random_sample(N,I-1,[R|Chosen0],Chosen) |
|||
; |
|||
random_sample(N,I,Chosen0,Chosen) |
|||
). |
|||
</syntaxhighlight> |
|||
=={{header|PicoLisp}}== |
|||
<syntaxhighlight lang="lisp">(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)" ) ) ) |
|||
</syntaxhighlight> |
|||
=={{header|PowerShell}}== |
|||
<syntaxhighlight lang="powershell"> |
|||
[int]$guesses = $bulls = $cows = 0 |
|||
[string]$guess = "none" |
|||
[string]$digits = "" |
|||
while ($digits.Length -lt 4) |
|||
{ |
|||
$character = [char](49..57 | Get-Random) |
|||
if ($digits.IndexOf($character) -eq -1) {$digits += $character} |
|||
} |
|||
Write-Host "`nGuess four digits (1-9) using no digit twice.`n" -ForegroundColor Cyan |
|||
while ($bulls -lt 4) |
|||
{ |
|||
do |
|||
{ |
|||
$prompt = "Guesses={0:0#}, Last='{1,4}', Bulls={2}, Cows={3}; Enter your guess" -f $guesses, $guess, $bulls, $cows |
|||
$guess = Read-Host $prompt |
|||
if ($guess.Length -ne 4) {Write-Host "`nMust be a four-digit number`n" -ForegroundColor Red} |
|||
if ($guess -notmatch "[1-9][1-9][1-9][1-9]") {Write-Host "`nMust be numbers 1-9`n" -ForegroundColor Red} |
|||
} |
|||
until ($guess.Length -eq 4) |
|||
$guesses += 1 |
|||
$bulls = $cows = 0 |
|||
for ($i = 0; $i -lt 4; $i++) |
|||
{ |
|||
$character = $digits.Substring($i,1) |
|||
if ($guess.Substring($i,1) -eq $character) |
|||
{ |
|||
$bulls += 1 |
|||
} |
|||
else |
|||
{ |
|||
if ($guess.IndexOf($character) -ge 0) |
|||
{ |
|||
$cows += 1 |
|||
} |
|||
} |
|||
} |
|||
} |
|||
Write-Host "`nYou won after $($guesses - 1) guesses." -ForegroundColor Cyan |
|||
</syntaxhighlight> |
|||
{{Out}} |
|||
<pre> |
|||
Guess four digits (1-9) using no digit twice. |
|||
Guesses=00, Last='none', Bulls=0, Cows=0; Enter your guess: 1234 |
|||
Guesses=01, Last='1234', Bulls=0, Cows=3; Enter your guess: 2345 |
|||
Guesses=02, Last='2345', Bulls=1, Cows=2; Enter your guess: 2346 |
|||
Guesses=03, Last='2346', Bulls=1, Cows=1; Enter your guess: 2341 |
|||
Guesses=04, Last='2341', Bulls=1, Cows=2; Enter your guess: 3241 |
|||
Guesses=05, Last='3241', Bulls=0, Cows=3; Enter your guess: 4321 |
|||
Guesses=06, Last='4321', Bulls=1, Cows=2; Enter your guess: 5321 |
|||
Guesses=07, Last='5321', Bulls=2, Cows=2; Enter your guess: 5312 |
|||
You won after 7 guesses. |
|||
</pre> |
|||
=={{header|Processing}}== |
|||
Produces both a console transcript and a GUI interface to the game. |
|||
Creates a new game each time the guess is correct; tracks number of games won. |
|||
<syntaxhighlight lang="processing">IntDict score; |
|||
StringList choices; |
|||
StringList guess; |
|||
StringList secret; |
|||
int gamesWon = -1; |
|||
void setup() { |
|||
choices = new StringList("0", "1", "2", "3", "4", "5", "6", "7", "8", "9"); |
|||
newGame(); |
|||
} |
|||
void newGame() { |
|||
gamesWon++; |
|||
choices.shuffle(); |
|||
secret = new StringList(); |
|||
for (int i=0; i<4; i++) { // selections |
|||
secret.append(choices.get(i)); |
|||
} |
|||
newGuess(); |
|||
println("\nsecret:", secret, "\n"); |
|||
} |
|||
void newGuess() { |
|||
guess = new StringList(); |
|||
score = null; |
|||
} |
|||
void draw() { |
|||
background(0); |
|||
text("Bulls & Cows " + gamesWon, 5, 20); |
|||
for (int i=0; i<guess.size(); i++) { |
|||
text(guess.get(i), 20*i+10, height/2); |
|||
} |
|||
if (score!=null) { |
|||
text("bulls:" + score.get("bulls") + " cows:" + score.get("cows"), 10, height-20); |
|||
} |
|||
} |
|||
void keyReleased() { |
|||
if (score!=null && score.get("bulls")==4) newGame(); |
|||
if (guess.size()==secret.size()) newGuess(); |
|||
if (guess.hasValue(str(key))) newGuess(); |
|||
if (key>=48 && key<=57) guess.append(str(key)); |
|||
if (guess.size()==secret.size()) { |
|||
score = checkScore(secret, guess); |
|||
println("guess: ", guess, "\n", score, "wins:", gamesWon); |
|||
} |
|||
} |
|||
IntDict checkScore(StringList secret, StringList guess) { |
|||
IntDict result = new IntDict(); |
|||
result.set("bulls", 0); |
|||
result.set("cows", 0); |
|||
for (int i=0; i<guess.size(); i++) { |
|||
if (guess.get(i).equals(secret.get(i))) { |
|||
result.add("bulls", 1); |
|||
} else if (secret.hasValue(guess.get(i))) { |
|||
result.add("cows", 1); |
|||
} |
|||
} |
|||
return result; |
|||
}</syntaxhighlight> |
|||
=={{header|Prolog}}== |
|||
Works with SWI-Prolog 6.1.8 (for predicate '''foldl'''), module lambda, written by '''Ulrich Neumerkel''' found there http://www.complang.tuwien.ac.at/ulrich/Prolog-inedit/lambda.pl and module clpfd written by '''Markus Triska'''. |
|||
<syntaxhighlight lang="prolog">:- use_module(library(lambda)). |
|||
:- use_module(library(clpfd)). |
|||
% Parameters of the server |
|||
% length of the guess |
|||
proposition(4). |
|||
% Numbers of digits |
|||
% 0 -> 8 |
|||
digits(8). |
|||
bulls_and_cows_server :- |
|||
proposition(LenGuess), |
|||
length(Solution, LenGuess), |
|||
choose(Solution), |
|||
repeat, |
|||
write('Your guess : '), |
|||
read(Guess), |
|||
( study(Solution, Guess, Bulls, Cows) |
|||
-> format('Bulls : ~w Cows : ~w~n', [Bulls, Cows]), |
|||
Bulls = LenGuess |
|||
; digits(Digits), Max is Digits + 1, |
|||
format('Guess must be of ~w digits between 1 and ~w~n', |
|||
[LenGuess, Max]), |
|||
fail). |
|||
choose(Solution) :- |
|||
digits(Digits), |
|||
Max is Digits + 1, |
|||
repeat, |
|||
maplist(\X^(X is random(Max) + 1), Solution), |
|||
all_distinct(Solution), |
|||
!. |
|||
study(Solution, Guess, Bulls, Cows) :- |
|||
proposition(LenGuess), |
|||
digits(Digits), |
|||
% compute the transformation 1234 => [1,2,3,4] |
|||
atom_chars(Guess, Chars), |
|||
maplist(\X^Y^(atom_number(X, Y)), Chars, Ms), |
|||
% check that the guess is well formed |
|||
length(Ms, LenGuess), |
|||
maplist(\X^(X > 0, X =< Digits+1), Ms), |
|||
% compute the digit in good place |
|||
foldl(\X^Y^V0^V1^((X = Y->V1 is V0+1; V1 = V0)),Solution, Ms, 0, Bulls), |
|||
% compute the digits in bad place |
|||
foldl(\Y1^V2^V3^(foldl(\X2^Z2^Z3^(X2 = Y1 -> Z3 is Z2+1; Z3 = Z2), Ms, 0, TT1), |
|||
V3 is V2+ TT1), |
|||
Solution, 0, TT), |
|||
Cows is TT - Bulls. |
|||
</syntaxhighlight> |
|||
=={{header|PureBasic}}== |
|||
<syntaxhighlight lang="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</syntaxhighlight> |
|||
=={{header|Python}}== |
=={{header|Python}}== |
||
< |
<syntaxhighlight lang="python">''' |
||
Bulls and cows. A game pre-dating, and similar to, Mastermind. |
Bulls and cows. A game pre-dating, and similar to, Mastermind. |
||
''' |
''' |
||
Line 1,072: | Line 6,120: | ||
elif guess[i] in chosen: |
elif guess[i] in chosen: |
||
cows += 1 |
cows += 1 |
||
print ' %i Bulls\n %i Cows' % (bulls, cows)</ |
print ' %i Bulls\n %i Cows' % (bulls, cows)</syntaxhighlight> |
||
Sample output: |
Sample output: |
||
<pre>I have chosen a number from 4 unique digits from 1 to 9 arranged in a random order. |
<pre>I have chosen a number from 4 unique digits from 1 to 9 arranged in a random order. |
||
Line 1,087: | Line 6,135: | ||
Congratulations you guessed correctly in 2 attempts</pre> |
Congratulations you guessed correctly in 2 attempts</pre> |
||
=={{header|QB64}}== |
|||
<syntaxhighlight lang="qb64"> |
|||
Const MaxDigit = 4, Min = 1, Max = 9 |
|||
Dim As String NumberToGuess, NumberToTest, Newdigit, Result |
|||
Dim As Integer Counter, Number |
|||
Randomize Timer |
|||
Do |
|||
Counter = Counter + 1 |
|||
Newdigit = _Trim$(Str$(Int(Rnd * Max) + Min)) |
|||
If InStr(NumberToGuess, Newdigit) = 0 Then NumberToGuess = NumberToGuess + Newdigit Else Counter = Counter - 1 |
|||
Loop While Counter < MaxDigit |
|||
Print NumberToGuess 'debug output |
|||
Do While NumberToGuess <> NumberToTest |
|||
Input "Please enter your guess of 4 digits... ", Number |
|||
NumberToTest = _Trim$(Str$(Number)) |
|||
If NumberToGuess <> NumberToTest Then |
|||
Result = "" |
|||
For Counter = 1 To 4 Step 1 |
|||
Newdigit = Mid$(NumberToTest, Counter, 1) |
|||
If InStr(NumberToGuess, Newdigit) - Counter = 0 Then |
|||
Result = Result + " Bull " |
|||
ElseIf InStr(NumberToGuess, Newdigit) > 0 Then |
|||
Result = Result + " Cow " |
|||
End If |
|||
Next Counter |
|||
Print NumberToTest, Result |
|||
Else |
|||
Print "You Win!" |
|||
End If |
|||
Loop |
|||
</syntaxhighlight> |
|||
=={{header|Quackery}}== |
|||
<code>transpose</code> is defined at [[Matrix transposition#Quackery]]. |
|||
<syntaxhighlight lang="Quackery"> [ size 4 = dup not if |
|||
[ say "Must be four digits." cr ] ] is 4chars ( $ --> b ) |
|||
[ true swap witheach |
|||
[ char 1 char 9 1+ within not if |
|||
[ say "Must be 1-9 only." cr |
|||
not conclude ] ] ] is 1-9 ( $ --> b ) |
|||
[ 0 9 of |
|||
swap witheach |
|||
[ 1 unrot char 1 - poke ] |
|||
0 swap witheach + |
|||
4 = dup not if |
|||
[ say "Must all be different." cr ] ] is all-diff ( $ --> b ) |
|||
[ $ "Guess four digits, 1-9, no duplicates: " |
|||
input |
|||
dup 4chars not iff drop again |
|||
dup 1-9 not iff drop again |
|||
dup all-diff not iff drop again ] is guess ( $ --> $ ) |
|||
[ $ "123456789" shuffle 4 split drop ] is rand$ ( --> $ ) |
|||
[ 2 pack transpose |
|||
[] swap witheach |
|||
[ dup unpack != iff |
|||
[ nested join ] |
|||
else drop ] |
|||
dup [] != if |
|||
[ transpose unpack ] |
|||
4 over size - ] is -bulls ( $ $ --> $ $ n ) |
|||
[ join sort |
|||
0 swap |
|||
behead swap witheach |
|||
[ tuck = if [ dip 1+ ] ] |
|||
drop ] is cows ( $ $ --> n ) |
|||
[ say "Guess the four numbers." cr cr |
|||
say "They are all different and" |
|||
say " between 1 and 9 inclusive." cr cr |
|||
randomise rand$ |
|||
[ guess |
|||
over -bulls |
|||
dup 4 = iff say "Correct." done |
|||
dup echo 1 = iff |
|||
[ say " bull." cr ] |
|||
else |
|||
[ say " bulls." cr ] |
|||
cows |
|||
dup echo 1 = iff |
|||
[ say " cow." cr ] |
|||
else |
|||
[ say " cows." cr ] |
|||
again ] |
|||
cr drop 2drop ] is play ( --> )</syntaxhighlight> |
|||
{{out}} |
|||
<pre>Guess the four numbers. |
|||
They are all different and between 1 and 9 inclusive. |
|||
Guess four digits, 1-9, no duplicates: 1234 |
|||
0 bulls. |
|||
0 cows. |
|||
Guess four digits, 1-9, no duplicates: 5678 |
|||
1 bull. |
|||
3 cows. |
|||
Guess four digits, 1-9, no duplicates: 5786 |
|||
1 bull. |
|||
3 cows. |
|||
Guess four digits, 1-9, no duplicates: 5867 |
|||
0 bulls. |
|||
4 cows. |
|||
Guess four digits, 1-9, no duplicates: 7658 |
|||
2 bulls. |
|||
2 cows. |
|||
Guess four digits, 1-9, no duplicates: 7685 |
|||
0 bulls. |
|||
4 cows. |
|||
Guess four digits, 1-9, no duplicates: 6758 |
|||
Correct. |
|||
</pre> |
|||
=={{header|R}}== |
=={{header|R}}== |
||
{{works with|R|2.8.1}} |
{{works with|R|2.8.1}} |
||
<syntaxhighlight lang="r">target <- sample(1:9,4) |
|||
<lang R> |
|||
target <- sample(1:9,4) |
|||
bulls <- 0 |
bulls <- 0 |
||
cows <- 0 |
cows <- 0 |
||
Line 1,109: | Line 6,277: | ||
} else {print("Malformed input!")} |
} else {print("Malformed input!")} |
||
} |
} |
||
print(paste("You won in",attempts,"attempt(s)!")) |
print(paste("You won in",attempts,"attempt(s)!"))</syntaxhighlight> |
||
=={{header|Racket}}== |
|||
</lang> |
|||
<syntaxhighlight lang="racket"> |
|||
#lang racket |
|||
; secret : (listof exact-nonnegative-integer?) |
|||
(define secret |
|||
(foldr (λ (n result) |
|||
(cons n (map (λ (y) (if (>= y n) (add1 y) y)) |
|||
result))) |
|||
'() |
|||
(map random '(10 9 8 7)))) |
|||
; (count-bulls/cows guess) -> (values exact-nonnegative-integer? |
|||
; exact-nonnegative-integer?) |
|||
; guess : (listof exact-nonnegative-integer?) |
|||
(define (count-bulls/cows guess) |
|||
(let* ([bulls (map = guess secret)] |
|||
[cow-candidates (filter-map (λ (x y) (if (false? x) y #f)) |
|||
bulls |
|||
secret)] |
|||
[cows (filter (curryr member cow-candidates) guess)]) |
|||
(values (length (filter ((curry equal?) #t) bulls)) |
|||
(length cows)))) |
|||
; (valid-guess guess-str) -> (or/c (listof exact-nonnegative-integer?) #f) |
|||
; guess-str : string? |
|||
(define (valid-guess guess-str) |
|||
(define (char->digit c) |
|||
(- (char->integer c) (char->integer #\0))) |
|||
(if (regexp-match-exact? #px"[0-9]{4}" guess-str) |
|||
(let ([guess (map char->digit (string->list guess-str))]) |
|||
(if (andmap (λ (x) (equal? (count ((curry equal?) x) guess) 1)) |
|||
guess) |
|||
guess |
|||
#f)) |
|||
#f)) |
|||
; Game states |
|||
(define win #t) |
|||
(define game #f) |
|||
; (main-loop state step) -> void? |
|||
; state : boolean? |
|||
; step : exact-nonnegative-integer? |
|||
(define (main-loop state step) |
|||
(if (equal? state win) |
|||
(printf "You won after ~a guesses." step) |
|||
(begin |
|||
(let* ([guess-str (read-line)] |
|||
[guess (valid-guess guess-str)]) |
|||
(if (false? guess) |
|||
(begin (displayln "Guess should include exactly four different digits") |
|||
(main-loop state step)) |
|||
(let-values ([(bulls cows) (count-bulls/cows guess)]) |
|||
(if (= bulls 4) |
|||
(main-loop win (add1 step)) |
|||
(begin (printf "Bulls: ~a Cows: ~a\n" bulls cows) |
|||
(main-loop state (add1 step)))))))))) |
|||
(main-loop game 0)</syntaxhighlight> |
|||
Output: |
|||
<pre> |
|||
1234 |
|||
Bulls: 0 Cows: 1 |
|||
21345 |
|||
Guess should include exactly four different digits |
|||
2134 |
|||
Bulls: 1 Cows: 0 |
|||
2314 |
|||
Bulls: 0 Cows: 1 |
|||
5167 |
|||
Bulls: 1 Cows: 1 |
|||
5189 |
|||
Bulls: 1 Cows: 2 |
|||
0189 |
|||
Bulls: 1 Cows: 2 |
|||
8179 |
|||
Bulls: 1 Cows: 3 |
|||
7198 |
|||
You won after 8 guesses. |
|||
</pre> |
|||
=={{header|Raku}}== |
|||
(formerly Perl 6) |
|||
{{trans|Python}} |
|||
{{works with|Rakudo|2015.12}} |
|||
<syntaxhighlight lang="raku" line>my $size = 4; |
|||
my @secret = pick $size, '1' .. '9'; |
|||
for 1..* -> $guesses { |
|||
my @guess; |
|||
loop { |
|||
@guess = (prompt("Guess $guesses: ") // exit).comb; |
|||
last if @guess == $size and |
|||
all(@guess) eq one(@guess) & any('1' .. '9'); |
|||
say 'Malformed guess; try again.'; |
|||
} |
|||
my ($bulls, $cows) = 0, 0; |
|||
for ^$size { |
|||
when @guess[$_] eq @secret[$_] { ++$bulls; } |
|||
when @guess[$_] eq any @secret { ++$cows; } |
|||
} |
|||
last if $bulls == $size; |
|||
say "$bulls bulls, $cows cows."; |
|||
} |
|||
say 'A winner is you!';</syntaxhighlight> |
|||
=={{header|Red}}== |
|||
<syntaxhighlight lang="red"> |
|||
Red[] |
|||
a: "0123456789" |
|||
bulls: 0 |
|||
random/seed now/time |
|||
number: copy/part random a 4 |
|||
while [bulls <> 4] [ |
|||
bulls: 0 |
|||
cows: 0 |
|||
guess: ask "make a guess: " |
|||
repeat i 4 [ |
|||
if (pick guess i) = (pick number i) [bulls: bulls + 1] |
|||
] |
|||
cows: (length? intersect guess number) - bulls |
|||
print ["bulls: " bulls " cows: " cows] |
|||
] |
|||
print "You won!" |
|||
</syntaxhighlight> |
|||
=={{header|REXX}}== |
|||
This game is also known as: |
|||
:::::::* Pigs and Bulls |
|||
:::::::* Bulls and Cleots |
|||
:::::::* Mastermind |
|||
:::::::* Master Mind |
|||
===version 1=== |
|||
'''See version 2 for a better formatted progtam that also runs on ooRexx.'''<br> |
|||
This REXX version of Bulls and Cows doesn't allow repeated digits (in the computer-generated number), |
|||
<br>nor the use of the zero digit. |
|||
<br><br>To allow a zero digit, change the <big> '''1''' </big> on the 2<sup>nd</sup> REXX statement for the '''random''' BIF invocation. |
|||
<br>To allow repeated digits in the computer-generated number, delete the 3<sup>rd</sup> REXX statement '''if pos(r, ?)···''', |
|||
<br>and also change the prompt message. |
|||
<br>The REXX statement that contains the '''translate''' statement can be removed if repeated digits aren't allowed. |
|||
<syntaxhighlight lang="rexx">/*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. */</syntaxhighlight><br><br> |
|||
===Version 2=== |
|||
<syntaxhighlight lang="rexx"> |
|||
/*REXX program to play the game of "Bulls & Cows". ******************* |
|||
* Changes from Version 1: |
|||
* ?= -> qq='' (righthandside mandatory and I never use ? as symbol - |
|||
* although it is available on all Rexxes) |
|||
* implemented singular/plural distinction differently |
|||
* change getRand to avoid invalid digit rejection |
|||
* check user's input for multiple digits |
|||
* add feature MM to ease guessing (MM=Mastermind - a similar game) |
|||
* add feature ? to see the solution (for the impatient player) |
|||
* program runs as is on ooRexx and on TSO (after changing | to !) |
|||
* Made source and output more compact |
|||
* formatted source 'my way' 2 July 2012 Walter Pachl |
|||
**********************************************************************/ |
|||
ask='<Bulls & Cows game> Please enter a four-digit guess (or QUIT):' |
|||
b.='bulls'; b.1='bull' |
|||
c.='cows'; c.1='cow' |
|||
qq=getRand() |
|||
mm=0 |
|||
Do Forever |
|||
If get_guess()==qq Then leave |
|||
Call scorer |
|||
Say "You got" bulls b.bulls "and" cows c.cows"." |
|||
If mm Then |
|||
Say mms |
|||
End /*forever*/ |
|||
Say " *******************************************" |
|||
Say " * *" |
|||
Say " * Congratulations, you've guessed it !! *" |
|||
Say " * *" |
|||
Say " *******************************************" |
|||
Exit |
|||
get_guess: /*get a guess from the guesser. */ |
|||
do forever |
|||
Say ask |
|||
Parse Pull guessi |
|||
guess=translate(guessi) |
|||
bc=verify(guess,987654321) |
|||
Select |
|||
When guess='?' Then Say qq 'is the correct sequence' |
|||
When guess='QUIT' Then Exit |
|||
When guess='MM' Then Do |
|||
Say 'Mastermind output enabled' |
|||
mm=1 |
|||
End |
|||
When guess='' Then Call ser 'no argument specified.' |
|||
When words(guess)>1 Then Call ser 'too many arguments specified.' |
|||
When verify(0,guess)=0 Then Call ser 'illegal digit: 0' |
|||
When bc>0 Then Call ser 'illegal character:' substr(guessi,bc,1) |
|||
When length(guess)<4 Then Call ser 'not enough digits' |
|||
When length(guess)>4 Then Call ser 'too many digits' |
|||
When dups(guess) Then Call ser '4 DIFFERENT digits, please' |
|||
Otherwise Do |
|||
/********** Say guess ************/ |
|||
Return guess |
|||
End |
|||
End |
|||
End |
|||
getRand: |
|||
digits='123456789' |
|||
qq='' |
|||
Do i=1 To 4 |
|||
d=random(1,length(digits)) |
|||
d=substr(digits,d,1) |
|||
qq=qq||d |
|||
digits=space(translate(digits,' ',d),0) |
|||
/************ Say qq digits ************/ |
|||
End |
|||
Return qq |
|||
scorer: g=qq |
|||
mms='----' |
|||
bulls=0 |
|||
Do j=1 for 4 |
|||
If substr(guess,j,1)=substr(qq,j,1) Then Do |
|||
bulls=bulls+1 |
|||
guess=overlay(' ',guess,j) |
|||
mms=overlay('+',mms,j) |
|||
End |
|||
End |
|||
cows=0 |
|||
Do j=1 To 4 |
|||
If pos(substr(guess,j,1),qq)>0 Then Do |
|||
cows=cows+1 |
|||
mms=overlay('.',mms,j) |
|||
End |
|||
End |
|||
Return |
|||
dups: Procedure |
|||
Parse Arg s |
|||
Do i=1 To 3 |
|||
If pos(substr(s,i,1),substr(s,i+1))>0 Then |
|||
Return 1 |
|||
End |
|||
Return 0 |
|||
ser: Say '*** error ***' arg(1); Return |
|||
</syntaxhighlight> |
|||
=={{header|Ring}}== |
|||
<syntaxhighlight lang="ring"> |
|||
# Project : Bulls and cows |
|||
secret = "" |
|||
while len(secret) != 4 |
|||
c = char(48 + random(9)) |
|||
if substr(secret, c) = 0 |
|||
secret = secret + c |
|||
ok |
|||
end |
|||
see "guess a four-digit number with no digit used twice." |
|||
guesses = 0 |
|||
guess = "" |
|||
while true |
|||
guess = "" |
|||
while len(guess) != 4 |
|||
see "enter your guess: " |
|||
give guess |
|||
if len(guess) != 4 |
|||
see "must be a four-digit number" + nl |
|||
ok |
|||
end |
|||
guesses = guesses + 1 |
|||
if guess = secret |
|||
see "you won after " + guesses + " guesses!" |
|||
exit |
|||
ok |
|||
bulls = 0 |
|||
cows = 0 |
|||
for i = 1 to 4 |
|||
c = secret[i] |
|||
if guess[i] = c |
|||
bulls = bulls + 1 |
|||
but substr(guess, c) > 0 |
|||
cows = cows + 1 |
|||
ok |
|||
next |
|||
see "you got " + bulls + " bull(s) and " + cows + " cow(s)." + nl |
|||
end |
|||
</syntaxhighlight> |
|||
=={{header|RPL}}== |
|||
{{works with|HP|49}} |
|||
« CLEAR 0 "" |
|||
1 4 '''START''' |
|||
'''WHILE''' RAND 9 * CEIL R→I →STR DUP2 POS '''REPEAT''' '''DROP''' END + |
|||
'''NEXT''' |
|||
→ count solution |
|||
« '''DO''' 1 CF |
|||
'''DO''' "Guess? [CONT]" PROMPT →STR |
|||
'''CASE''' |
|||
DUP SIZE 4 ≠ '''THEN''' DROP "Not 4 characters" 1 DISP 0.5 WAIT '''END''' |
|||
{ 9 } 0 CON |
|||
1 4 '''FOR''' j |
|||
OVER j DUP SUB STR→ |
|||
'''IFERR''' 1 PUT '''THEN''' 3 DROPN "Invalid character" 1 DISP 0.5 WAIT '''END''' |
|||
'''NEXT''' |
|||
DUP 1 CON DOT 4 ≠ '''THEN''' DROP "Repeated digits" 1 DISP 0.5 WAIT '''END''' |
|||
1 SF |
|||
'''END''' |
|||
'''UNTIL''' 1 FS? '''END''' |
|||
" → " + 0 |
|||
1 4 '''FOR''' j |
|||
solution PICK3 j DUP SUB POS |
|||
'''IF''' DUP '''THEN''' IF j == '''THEN''' 1 '''ELSE''' .1 '''END END''' + |
|||
'''NEXT''' |
|||
SWAP OVER + 'count' INCR DROP |
|||
'''UNTIL''' SWAP 4 == '''END''' |
|||
count "guess" →TAG |
|||
» » '<span style="color:blue">BU&CO</span>' ST0 |
|||
=={{header|Ruby}}== |
=={{header|Ruby}}== |
||
Inspired by Tcl |
Inspired by Tcl |
||
{{works with|Ruby|1.8.7+}} |
|||
<lang ruby>def generate_word(len) |
|||
<syntaxhighlight lang="ruby">def generate_word(len) |
|||
([1, 2, 3, 4, 5, 6, 7, 8, 9].shuffle)[0,len].join("") |
|||
[*"1".."9"].shuffle.first(len) # [*"1".."9"].sample(len) ver 1.9+ |
|||
end |
end |
||
def get_guess(len) |
def get_guess(len) |
||
loop do |
|||
print "Enter a guess: " |
print "Enter a guess: " |
||
guess = gets.strip |
guess = gets.strip |
||
err = case |
err = case |
||
when guess.match(/ |
when guess.match(/[^1-9]/) ; "digits only" |
||
when guess.length != len |
when guess.length != len ; "exactly #{len} digits" |
||
when guess.split("").uniq.length != len |
when guess.split("").uniq.length != len; "digits must be unique" |
||
else |
else return guess.split("") |
||
end |
end |
||
puts "the word must be #{len} unique digits between 1 and 9 (#{err}). Try again." |
|||
break if err.nil? |
|||
puts "the word must be #{len} unique digits between 1 and 9 (#{err}). Try again." |
|||
end |
end |
||
guess |
|||
end |
end |
||
def score(word, guess) |
def score(word, guess) |
||
bulls = cows = 0 |
bulls = cows = 0 |
||
guess |
guess.each_with_index do |num, idx| |
||
if word[idx] == |
if word[idx] == num |
||
bulls += 1 |
bulls += 1 |
||
elsif word.include? |
elsif word.include? num |
||
cows += 1 |
cows += 1 |
||
end |
end |
||
Line 1,146: | Line 6,659: | ||
end |
end |
||
srand |
|||
word_length = 4 |
word_length = 4 |
||
puts "I have chosen a number with #{word_length} unique digits from 1 to 9." |
puts "I have chosen a number with #{word_length} unique digits from 1 to 9." |
||
word = generate_word(word_length) |
word = generate_word(word_length) |
||
count = 0 |
count = 0 |
||
loop do |
|||
while true |
|||
guess = get_guess(word_length) |
guess = get_guess(word_length) |
||
count += 1 |
count += 1 |
||
Line 1,157: | Line 6,669: | ||
puts "that guess has %d bulls and %d cows" % score(word, guess) |
puts "that guess has %d bulls and %d cows" % score(word, guess) |
||
end |
end |
||
puts "you guessed correctly in #{count} tries."</ |
puts "you guessed correctly in #{count} tries."</syntaxhighlight> |
||
Inspired by Python |
|||
{{works with|Ruby|2.0+}} |
|||
<syntaxhighlight lang="ruby">size = 4 |
|||
secret = [*'1' .. '9'].sample(size) |
|||
guess = nil |
|||
i=0 |
|||
loop do |
|||
i+=1 |
|||
loop do |
|||
print "Guess #{i}: " |
|||
guess = gets.chomp.chars |
|||
exit if guess.empty? |
|||
break if guess.size == size and |
|||
guess.all? { |x| ('1'..'9').include? x } and |
|||
guess.uniq.size == size |
|||
puts "Problem, try again. You need to enter #{size} unique digits from 1 to 9" |
|||
end |
|||
if guess == secret |
|||
puts "Congratulations you guessed correctly in #{i} attempts" |
|||
break |
|||
end |
|||
bulls = cows = 0 |
|||
size.times do |j| |
|||
if guess[j] == secret[j] |
|||
bulls += 1 |
|||
elsif secret.include? guess[j] |
|||
cows += 1 |
|||
end |
|||
end |
|||
puts "Bulls: #{bulls}; Cows: #{cows}" |
|||
end</syntaxhighlight> |
|||
=={{header|Rust}}== |
|||
{{libheader|rand}} |
|||
<syntaxhighlight lang="rust">use std::io; |
|||
use rand::{Rng,thread_rng}; |
|||
extern crate rand; |
|||
const NUMBER_OF_DIGITS: usize = 4; |
|||
static DIGITS: [char; 9] = ['1', '2', '3', '4', '5', '6', '7', '8', '9']; |
|||
fn generate_digits() -> Vec<char> { |
|||
let mut temp_digits: Vec<_> = (&DIGITS[..]).into(); |
|||
thread_rng().shuffle(&mut temp_digits); |
|||
return temp_digits.iter().take(NUMBER_OF_DIGITS).map(|&a| a).collect(); |
|||
} |
|||
fn parse_guess_string(guess: &str) -> Result<Vec<char>, String> { |
|||
let chars: Vec<char> = (&guess).chars().collect(); |
|||
if !chars.iter().all(|c| DIGITS.contains(c)) { |
|||
return Err("only digits, please".to_string()); |
|||
} |
|||
if chars.len() != NUMBER_OF_DIGITS { |
|||
return Err(format!("you need to guess with {} digits", NUMBER_OF_DIGITS)); |
|||
} |
|||
let mut uniques: Vec<char> = chars.clone(); |
|||
uniques.dedup(); |
|||
if uniques.len() != chars.len() { |
|||
return Err("no duplicates, please".to_string()); |
|||
} |
|||
return Ok(chars); |
|||
} |
|||
fn calculate_score(given_digits: &[char], guessed_digits: &[char]) -> (usize, usize) { |
|||
let mut bulls = 0; |
|||
let mut cows = 0; |
|||
for i in 0..NUMBER_OF_DIGITS { |
|||
let pos: Option<usize> = guessed_digits.iter().position(|&a| -> bool {a == given_digits[i]}); |
|||
match pos { |
|||
None => (), |
|||
Some(p) if p == i => bulls += 1, |
|||
Some(_) => cows += 1 |
|||
} |
|||
} |
|||
return (bulls, cows); |
|||
} |
|||
fn main() { |
|||
let reader = io::stdin(); |
|||
loop { |
|||
let given_digits = generate_digits(); |
|||
println!("I have chosen my {} digits. Please guess what they are", NUMBER_OF_DIGITS); |
|||
loop { |
|||
let guess_string: String = { |
|||
let mut buf = String::new(); |
|||
reader.read_line(&mut buf).unwrap(); |
|||
buf.trim().into() |
|||
}; |
|||
let digits_maybe = parse_guess_string(&guess_string); |
|||
match digits_maybe { |
|||
Err(msg) => { |
|||
println!("{}", msg); |
|||
continue; |
|||
}, |
|||
Ok(guess_digits) => { |
|||
match calculate_score(&given_digits, &guess_digits) { |
|||
(NUMBER_OF_DIGITS, _) => { |
|||
println!("you win!"); |
|||
break; |
|||
}, |
|||
(bulls, cows) => println!("bulls: {}, cows: {}", bulls, cows) |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
}</syntaxhighlight> |
|||
=={{header|Scala}}== |
|||
<syntaxhighlight lang="scala">import scala.util.Random |
|||
object BullCow { |
|||
def main(args: Array[String]): Unit = { |
|||
val number=chooseNumber |
|||
var guessed=false |
|||
var guesses=0 |
|||
while(!guessed){ |
|||
Console.print("Guess a 4-digit number with no duplicate digits: ") |
|||
val input=Console.readInt |
|||
val digits=input.toString.map(_.asDigit).toList |
|||
if(input>=1111 && input<=9999 && !hasDups(digits)){ |
|||
guesses+=1 |
|||
var bulls, cows=0 |
|||
for(i <- 0 to 3) |
|||
if(number(i)==digits(i)) |
|||
bulls+=1 |
|||
else if(number.contains(digits(i))) |
|||
cows+=1 |
|||
if(bulls==4) |
|||
guessed=true |
|||
else |
|||
println("%d Cows and %d Bulls.".format(cows, bulls)) |
|||
} |
|||
} |
|||
println("You won after "+guesses+" guesses!"); |
|||
} |
|||
def chooseNumber={ |
|||
var digits=List[Int]() |
|||
while(digits.size<4){ |
|||
val d=Random.nextInt(9)+1 |
|||
if (!digits.contains(d)) |
|||
digits=digits:+d |
|||
} |
|||
digits |
|||
} |
|||
def hasDups(input:List[Int])=input.size!=input.distinct.size |
|||
}</syntaxhighlight> |
|||
=={{header|Scheme}}== |
|||
{{works with|any R6RS Scheme}} |
|||
<syntaxhighlight lang="scheme"> |
|||
;generate a random non-repeating list of 4 digits, 1-9 inclusive |
|||
(define (get-num) |
|||
(define (gen lst) |
|||
(if (= (length lst) 4) lst |
|||
(let ((digit (+ (random 9) 1))) |
|||
(if (member digit lst) ;make sure the new digit isn't in the |
|||
;list |
|||
(gen lst) |
|||
(gen (cons digit lst)))))) |
|||
(string->list (apply string-append (map number->string (gen '()))))) |
|||
;is g a valid guess (that is, non-repeating, four digits 1-9 |
|||
;inclusive?) |
|||
(define (valid-guess? g) |
|||
(let ((g-num (string->number (apply string g)))) |
|||
;does the same digit appear twice in lst? |
|||
(define (repeats? lst) |
|||
(cond ((null? lst) #f) |
|||
((member (car lst) (cdr lst)) #t) |
|||
(else (repeats? (cdr lst))))) |
|||
(and g-num |
|||
(> g-num 1233) |
|||
(< g-num 9877) |
|||
(not (repeats? g))))) |
|||
;return '(cows bulls) for the given guess |
|||
(define (score answer guess) |
|||
;total cows + bulls |
|||
(define (cows&bulls a g) |
|||
(cond ((null? a) 0) |
|||
((member (car a) g) (+ 1 (cows&bulls (cdr a) g))) |
|||
(else (cows&bulls (cdr a) g)))) |
|||
;bulls only |
|||
(define (bulls a g) |
|||
(cond ((null? a) 0) |
|||
((equal? (car a) (car g)) (+ 1 (bulls (cdr a) (cdr g)))) |
|||
(else (bulls (cdr a) (cdr g))))) |
|||
(list (- (cows&bulls answer guess) (bulls answer guess)) (bulls answer guess))) |
|||
;play the game |
|||
(define (bull-cow answer) |
|||
;get the user's guess as a list |
|||
(define (get-guess) |
|||
(let ((e (read))) |
|||
(if (number? e) |
|||
(string->list (number->string e)) |
|||
(string->list (symbol->string e))))) |
|||
(display "Enter a guess: ") |
|||
(let ((guess (get-guess))) |
|||
(if (valid-guess? guess) |
|||
(let ((bulls (cadr (score answer guess))) |
|||
(cows (car (score answer guess)))) |
|||
(if (= bulls 4) |
|||
(display "You win!\n") |
|||
(begin |
|||
(display bulls) |
|||
(display " bulls, ") |
|||
(display cows) |
|||
(display " cows.\n") |
|||
(bull-cow answer)))) |
|||
(begin |
|||
(display "Invalid guess.\n") |
|||
(bull-cow answer))))) |
|||
(bull-cow (get-num)) |
|||
</syntaxhighlight> |
|||
=== Sample game play === |
|||
<pre> |
|||
Enter a guess: 1234 |
|||
0 bulls, 1 cows. |
|||
Enter a guess: 2345 |
|||
1 bulls, 0 cows. |
|||
Enter a guess: 2346 |
|||
1 bulls, 1 cows. |
|||
Enter a guess: 2367 |
|||
0 bulls, 1 cows. |
|||
Enter a guess: 2647 |
|||
1 bulls, 1 cows. |
|||
Enter a guess: 2648 |
|||
2 bulls, 1 cows. |
|||
Enter a guess: 2468 |
|||
1 bulls, 2 cows. |
|||
Enter a guess: 1468 |
|||
1 bulls, 2 cows. |
|||
Enter a guess: 2684 |
|||
0 bulls, 3 cows. |
|||
Enter a guess: 6248 |
|||
3 bulls, 0 cows. |
|||
Enter a guess: 6948 |
|||
You win! |
|||
</pre> |
|||
=={{header|Scratch}}== |
|||
Scratch is a graphical programming language. Follow the link to see an example solution for Bulls and Cows<br> |
|||
[https://scratch.mit.edu/projects/370296926/ '''Scratch - Bulls and Cows''']<br> |
|||
<br> |
|||
The program "says" the score of the current guess and uses a list to display previous guesses.<br> |
|||
Malformed guesses are rejected for the following reasons: |
|||
* Guess is longer or shorter than 4 characters |
|||
* Guess contains character other than the digits 1 - 9 |
|||
* Guess contains a digit more than once (i.e. 3484 - this would be rejected because "4" appears in the guess two times) |
|||
<br> |
|||
Since Scratch is an educational language, I've included comments in the code to explain what the program is doing.<br> |
|||
=={{header|Seed7}}== |
|||
<syntaxhighlight lang="seed7">$ include "seed7_05.s7i"; |
|||
const proc: main is func |
|||
local |
|||
const integer: size is 4; |
|||
var set of char: digits is {'1' .. '9'}; |
|||
var string: chosen is " " mult size; |
|||
var integer: guesses is 0; |
|||
var string: guess is ""; |
|||
var integer: pos is 0; |
|||
var integer: bulls is 0; |
|||
var integer: cows is 0; |
|||
var boolean: okay is FALSE; |
|||
begin |
|||
for pos range 1 to 4 do |
|||
chosen @:= [pos] rand(digits); |
|||
excl(digits, chosen[pos]); |
|||
end for; |
|||
writeln("I have chosen a number from " <& size <& " unique digits from 1 to 9 arranged in a random order."); |
|||
writeln("You need to input a " <& size <& " digit, unique digit number as a guess at what I have chosen"); |
|||
repeat |
|||
incr(guesses); |
|||
repeat |
|||
write("Next guess [" <& guesses <& "]: "); |
|||
readln(guess); |
|||
okay := length(guess) = size; |
|||
for key pos range guess do |
|||
okay := okay and guess[pos] in {'1' .. '9'} and pos(guess[succ(pos) ..], guess[pos]) = 0; |
|||
end for; |
|||
if not okay then |
|||
writeln("Problem, try again. You need to enter " <& size <& " unique digits from 1 to 9"); |
|||
end if; |
|||
until okay; |
|||
if guess <> chosen then |
|||
bulls := 0; |
|||
cows := 0; |
|||
for key pos range chosen do |
|||
if guess[pos] = chosen[pos] then |
|||
incr(bulls); |
|||
elsif pos(chosen, guess[pos]) <> 0 then |
|||
incr(cows); |
|||
end if; |
|||
end for; |
|||
writeln(" " <& bulls <& " Bulls"); |
|||
writeln(" " <& cows <& " Cows"); |
|||
end if; |
|||
until guess = chosen; |
|||
writeln("Congratulations you guessed correctly in " <& guesses <& " attempts"); |
|||
end func;</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
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]: 1234 |
|||
1 Bulls |
|||
0 Cows |
|||
Next guess [2]: 1567 |
|||
1 Bulls |
|||
2 Cows |
|||
Next guess [3]: 1856 |
|||
3 Bulls |
|||
0 Cows |
|||
Next guess [4]: 1956 |
|||
Congratulations you guessed correctly in 4 attempts |
|||
</pre> |
|||
=={{header|SenseTalk}}== |
|||
<syntaxhighlight lang="sensetalk">repeat forever |
|||
repeat forever |
|||
put random(1111,9999) into num |
|||
if character 1 of num is not equal to character 2 of num |
|||
if character 1 of num is not equal to character 3 of num |
|||
if character 1 of num is not equal to character 4 of num |
|||
if character 2 of num is not equal to character 3 of num |
|||
if character 2 of num is not equal to character 4 of num |
|||
if character 3 of num is not equal to character 4 of num |
|||
if num does not contain 0 |
|||
exit repeat |
|||
end if |
|||
end if |
|||
end if |
|||
end if |
|||
end if |
|||
end if |
|||
end if |
|||
end repeat |
|||
set description to "Guess the 4 digit number" & newline & "- zero's excluded" & newline & "- each digit is unique" & newline & newline & "Receive 1 Bull for each digit that equals the corresponding digit in the random number." & newline & newline & "Receive 1 Cow for each digit that appears in the wrong position." & newline |
|||
repeat forever |
|||
repeat forever |
|||
Ask "Guess the number" title "Bulls & Cows" message description |
|||
put it into guess |
|||
if number of characters in guess is equal to 4 |
|||
exit repeat |
|||
else if guess is "" |
|||
Answer "" with "Play" or "Quit" title "Quit Bulls & Cows?" |
|||
put it into myAnswer |
|||
if myAnswer is "Quit" |
|||
exit all |
|||
end if |
|||
end if |
|||
end repeat |
|||
set score to { |
|||
bulls: { |
|||
qty: 0, |
|||
values: [] |
|||
}, |
|||
cows: { |
|||
qty: 0, |
|||
values: [] |
|||
} |
|||
} |
|||
repeat the number of characters in num times |
|||
if character the counter of guess is equal to character the counter of num |
|||
add 1 to score.bulls.qty |
|||
insert character the counter of guess into score.bulls.values |
|||
else |
|||
if num contains character the counter of guess |
|||
if character the counter of guess is not equal to character the counter of num |
|||
if score.bulls.values does not contain character the counter of guess and score.cows.values does not contain character the counter of guess |
|||
add 1 to score.cows.qty |
|||
insert character the counter of guess into score.cows.values |
|||
end if |
|||
end if |
|||
end if |
|||
end if |
|||
end repeat |
|||
set showScores to "Your score is:" & newline & newline & "Bulls:" && score.bulls.qty & newline & newline & "Cows:" && score.cows.qty |
|||
if guess is not equal to num |
|||
Answer showScores with "Guess Again" or "Quit" title "Score" |
|||
put it into myAnswer |
|||
if myAnswer is "Quit" |
|||
exit all |
|||
end if |
|||
else |
|||
set winShowScores to showScores & newline & newline & "Your Guess:" && guess & newline & "Random Number:" && num & newline |
|||
Answer winShowScores with "Play Again" or "Quit" title "You Win!" |
|||
put it into myAnswer |
|||
if myAnswer is "Quit" |
|||
exit all |
|||
end if |
|||
exit repeat |
|||
end if |
|||
end repeat |
|||
end repeat</syntaxhighlight> |
|||
=={{header|SETL}}== |
|||
<syntaxhighlight lang="setl">program bulls_and_cows; |
|||
setrandom(0); |
|||
print("Bulls and cows"); |
|||
print("--------------"); |
|||
print; |
|||
secret := make_secret(); |
|||
loop do |
|||
guess := read_guess(); |
|||
tries +:= 1; |
|||
bulls := count_bulls(guess, secret); |
|||
cows := count_cows(guess, secret); |
|||
print(bulls, "bulls,", cows, "cows."); |
|||
if bulls = 4 then |
|||
print("You win! Tries:", tries); |
|||
exit; |
|||
end if; |
|||
end loop; |
|||
proc make_secret(); |
|||
digits := []; |
|||
loop for i in [1..4] do |
|||
loop until not digit in digits do |
|||
digit := 1 + random(8); |
|||
end loop; |
|||
digits with:= digit; |
|||
end loop; |
|||
return digits; |
|||
end proc; |
|||
proc read_guess(); |
|||
loop do |
|||
putchar("Guess? "); |
|||
flush(stdout); |
|||
guess := getline(stdin); |
|||
if exists d in guess | not d in "123456789" then |
|||
print("invalid input:", d); |
|||
elseif #guess /= #{d : d in guess} then |
|||
print("no duplicates allowed"); |
|||
elseif #guess /= 4 then |
|||
print("need 4 digits"); |
|||
else |
|||
exit; |
|||
end if; |
|||
end loop; |
|||
return [val d : d in guess]; |
|||
end proc; |
|||
proc count_bulls(guess, secret); |
|||
return #[i : i in [1..4] | guess(i) = secret(i)]; |
|||
end proc; |
|||
proc count_cows(guess, secret); |
|||
return #[d : d in guess | d in secret] - count_bulls(guess, secret); |
|||
end proc; |
|||
end program;</syntaxhighlight> |
|||
{{out}} |
|||
<pre>Bulls and cows |
|||
-------------- |
|||
Guess? 1234 |
|||
0 bulls, 1 cows. |
|||
Guess? 5678 |
|||
2 bulls, 1 cows. |
|||
Guess? 5978 |
|||
2 bulls, 0 cows. |
|||
Guess? 5968 |
|||
1 bulls, 1 cows. |
|||
Guess? 5976 |
|||
1 bulls, 1 cows. |
|||
Guess? 6978 |
|||
3 bulls, 0 cows. |
|||
Guess? 6971 |
|||
2 bulls, 0 cows. |
|||
Guess? 6918 |
|||
2 bulls, 0 cows. |
|||
Guess? 1978 |
|||
2 bulls, 0 cows. |
|||
Guess? 6178 |
|||
3 bulls, 0 cows. |
|||
Guess? 6278 |
|||
3 bulls, 0 cows. |
|||
Guess? 6378 |
|||
4 bulls, 0 cows. |
|||
You win! Tries: 12</pre> |
|||
=={{header|Shale}}== |
|||
<syntaxhighlight lang="shale">#!/usr/local/bin/shale |
|||
maths library |
|||
file library |
|||
string library |
|||
n0 var |
|||
n1 var |
|||
n2 var |
|||
n3 var |
|||
g0 var |
|||
g1 var |
|||
g2 var |
|||
g3 var |
|||
init dup var { |
|||
c guess:: var |
|||
} = |
|||
getNum dup var { |
|||
random maths::() 15 >> 9 % 1 + |
|||
} = |
|||
game dup var { |
|||
haveWon dup var false = |
|||
ans var |
|||
i var |
|||
c var |
|||
b var |
|||
c guess:: 0 = |
|||
n0 getNum() = |
|||
n1 getNum() = |
|||
{ n1 n0 == } { |
|||
n1 getNum() = |
|||
} while |
|||
n2 getNum() = |
|||
{ n2 n0 == n2 n1 == or } { |
|||
n2 getNum() = |
|||
} while |
|||
n3 getNum() = |
|||
{ n3 n0 == n3 n1 == n3 n2 == or or } { |
|||
n3 getNum() = |
|||
} while |
|||
"New game" println |
|||
{ haveWon not } { |
|||
"> " print |
|||
stdin file:: fgets file::() { |
|||
ans swap atoi string::() = |
|||
g3 ans 10 % = |
|||
g2 ans 10 / 10 % = |
|||
g1 ans 100 / 10 % = |
|||
g0 ans 1000 / 10 % = |
|||
g0 0 > g0 10 < and g1 0 > g1 10 < and g2 0 > g2 10 < and g3 0 > g3 10 < and and and and { |
|||
c 0 = |
|||
b 0 = |
|||
g0 n0 == { |
|||
b++ |
|||
} { |
|||
g0 n1 == g0 n2 == g0 n3 == or or { c++ } ifthen |
|||
} if |
|||
g1 n1 == { |
|||
b++ |
|||
} { |
|||
g1 n0 == g1 n2 == g1 n3 == or or { c++ } ifthen |
|||
} if |
|||
g2 n2 == { |
|||
b++ |
|||
} { |
|||
g2 n0 == g2 n1 == g2 n3 == or or { c++ } ifthen |
|||
} if |
|||
g3 n3 == { |
|||
b++ |
|||
} { |
|||
g3 n0 == g3 n1 == g3 n2 == or or { c++ } ifthen |
|||
} if |
|||
i c guess:: = |
|||
i.value guess:: guess:: defined not { |
|||
i.value guess:: guess:: var |
|||
i.value cow:: guess:: var |
|||
i.value bull:: guess:: var |
|||
} ifthen |
|||
i.value guess:: guess:: ans = |
|||
i.value cow:: guess:: c = |
|||
i.value bull:: guess:: b = |
|||
c guess::++ |
|||
"Go Guess Cows Bulls" println |
|||
i 0 = |
|||
{ i c guess:: < } { |
|||
i.value bull:: guess:: i.value cow:: guess:: i.value guess:: guess:: i 1 + "%2d %d %4d %5d\n" printf |
|||
i++ |
|||
} while |
|||
b 4 == { haveWon true = } ifthen |
|||
} { |
|||
"Illegal input" println |
|||
} if |
|||
} { |
|||
0 exit |
|||
} if |
|||
} while |
|||
} = |
|||
play dup var { |
|||
{ true } { |
|||
game() |
|||
} while |
|||
} = |
|||
init() |
|||
play()</syntaxhighlight> |
|||
{{out}} |
|||
<pre>New game |
|||
> 1234 |
|||
Go Guess Cows Bulls |
|||
1 1234 2 0 |
|||
> 2345 |
|||
Go Guess Cows Bulls |
|||
1 1234 2 0 |
|||
2 2345 2 0 |
|||
> 3456 |
|||
Go Guess Cows Bulls |
|||
1 1234 2 0 |
|||
2 2345 2 0 |
|||
3 3456 0 2 |
|||
> 4567 |
|||
Go Guess Cows Bulls |
|||
1 1234 2 0 |
|||
2 2345 2 0 |
|||
3 3456 0 2 |
|||
4 4567 1 0 |
|||
> 5678 |
|||
Go Guess Cows Bulls |
|||
1 1234 2 0 |
|||
2 2345 2 0 |
|||
3 3456 0 2 |
|||
4 4567 1 0 |
|||
5 5678 1 1 |
|||
> 6789 |
|||
Go Guess Cows Bulls |
|||
1 1234 2 0 |
|||
2 2345 2 0 |
|||
3 3456 0 2 |
|||
4 4567 1 0 |
|||
5 5678 1 1 |
|||
6 6789 1 0 |
|||
> 3158 |
|||
Go Guess Cows Bulls |
|||
1 1234 2 0 |
|||
2 2345 2 0 |
|||
3 3456 0 2 |
|||
4 4567 1 0 |
|||
5 5678 1 1 |
|||
6 6789 1 0 |
|||
7 3158 0 4 |
|||
New game |
|||
></pre> |
|||
=={{header|Sidef}}== |
|||
<syntaxhighlight lang="ruby">var size = 4 |
|||
var num = @(1..9).shuffle.first(size) |
|||
for (var guesses = 1; true; guesses++) { |
|||
var bulls = 0 |
|||
var cows = 0 |
|||
var input = |
|||
read("Input: ", String).chars \ |
|||
.uniq \ |
|||
.grep(/^[1-9]$/) \ |
|||
.map{.to_n} |
|||
if (input.len != size) { |
|||
warn "Invalid input!\n" |
|||
guesses-- |
|||
next |
|||
} |
|||
if (input == num) { |
|||
printf("You did it in %d attempts!\n", guesses) |
|||
break |
|||
} |
|||
for i (^num) { |
|||
if (num[i] == input[i]) { |
|||
bulls++ |
|||
} |
|||
elsif (num.contains(input[i])) { |
|||
cows++ |
|||
} |
|||
} |
|||
"Bulls: %d; Cows: %d\n".printf(bulls, cows) |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Input: 2953 |
|||
Bulls: 1; Cows: 1 |
|||
Input: 9654 |
|||
Bulls: 1; Cows: 1 |
|||
Input: 8924 |
|||
Bulls: 1; Cows: 3 |
|||
Input: 2894 |
|||
You did it in 4 attempts! |
|||
</pre> |
|||
=={{header|Smalltalk}}== |
=={{header|Smalltalk}}== |
||
{{works with|GNU Smalltalk}} |
{{works with|GNU Smalltalk}} |
||
< |
<syntaxhighlight lang="smalltalk">Object subclass: BullsCows [ |
||
|number| |
|number| |
||
BullsCows class >> new: secretNum [ |i| |
BullsCows class >> new: secretNum [ |i| |
||
Line 1,218: | Line 7,455: | ||
'Do you want to play again? [y/n]' display. |
'Do you want to play again? [y/n]' display. |
||
( (stdin nextLine) = 'y' ) |
( (stdin nextLine) = 'y' ) |
||
] whileTrue: [ Character nl displayNl ].</ |
] whileTrue: [ Character nl displayNl ].</syntaxhighlight> |
||
=={{header|Smart BASIC}}== |
|||
<syntaxhighlight lang="smart basic"> |
|||
'by rbytes, January 2017 |
|||
OPTION BASE 1 |
|||
P(" B U L L S A N D C O W S")!l |
|||
P("A secret 4-digit number has been created, with") |
|||
P("no repeats and no zeros. You must guess the number.") |
|||
P("After each guess, you will be shown how many of your") |
|||
P("digits are correct and in the matching location (bulls),") |
|||
P("and how many are correct but in a different location (cows).") |
|||
p("See how many tries it takes you to get the right answer.") |
|||
' generate a 4-digit number with no repeats |
|||
guesses = 0 |
|||
1 WHILE LEN(sec$) <4 |
|||
c$ =CHR$( INTEG(RND(1) *9) +49) |
|||
IF INSTR(sec$, c$)=-1 THEN sec$&=c$ |
|||
ENDWHILE!l |
|||
2 PRINT "Your guess: " |
|||
INPUT "FOUR DIGITS": guess$!l |
|||
IF guess$="" THEN ' check if entry is null |
|||
P("Please enter something!")!l |
|||
GOTO 2 |
|||
ENDIF |
|||
P(guess$)!l |
|||
IF LEN(guess$)<>4 THEN ' check if entry is exactly 4 characters |
|||
P("Please enter exactly 4 digits.")!l |
|||
GOTO 2 |
|||
ENDIF |
|||
FOR t=1 TO 4 ' check if all characters are digits 1 - 9 |
|||
IF INSTR("123456789",MID$(guess$,t,1))=-1 THEN |
|||
P("You have entered at least one illegal character")!l |
|||
GOTO 2 |
|||
ENDIF |
|||
NEXT t |
|||
rep = check(guess$) ' check if any digits are repeated |
|||
IF check.chk THEN |
|||
P("Please enter a number with no repeated digits.")!l |
|||
GOTO 2 |
|||
ENDIF |
|||
guesses+=1 |
|||
r$=score$(guess$,sec$) |
|||
P(r$)!l |
|||
IF guess$=sec$ THEN |
|||
P("W I N N E R ! ! !")!l |
|||
IF guesses>1 THEN gs$="guesses!" ELSE gs$="guess!" |
|||
P("You won after "&guesses&" "&gs$) |
|||
P("Thanks for playing!")!l |
|||
PAUSE 2 |
|||
P("A G A I N with a new secret number")!l |
|||
guesses=0 |
|||
END IF |
|||
GOTO 1 |
|||
END ' _____________________________________________________________ |
|||
DEF P(p$) ' function to print a string |
|||
PRINT p$ |
|||
END DEF |
|||
DEF L() ' function to print an empty line |
|||
PRINT |
|||
END DEF |
|||
DEF check(i$) ' check=0 if digit is not repeated, else=1 |
|||
chk=0 |
|||
FOR i =1 TO 3 |
|||
FOR j =i +1 TO 4 |
|||
IF MID$( i$, i, 1)=MID$( i$, j, 1) THEN chk =1 |
|||
NEXT j |
|||
NEXT i |
|||
END DEF |
|||
DEF score$(a$,b$) ' calculate the numbers of bulls & cows. |
|||
bulls=0!cows=0 |
|||
FOR i = 1 TO 4 |
|||
c$ = MID$( a$, i, 1) |
|||
IF MID$( b$, i, 1)=c$ THEN |
|||
bulls+=1 |
|||
ELSE |
|||
IF INSTR( b$, c$) <>-1 AND INSTR( b$, c$) <>i THEN |
|||
cows+=1 |
|||
END IF |
|||
END IF |
|||
NEXT i |
|||
r$ ="Bulls: "&STR$( bulls)& ", "& "Cows: " &STR$( cows) |
|||
RETURN r$ |
|||
END DEF |
|||
END |
|||
</syntaxhighlight> |
|||
=={{header|Swift}}== |
|||
{{works with|Swift|5.7}} |
|||
This is the same as the original solution but takes advantage of Swift 5's richer standard library to clean things up a bit. |
|||
<syntaxhighlight lang="swift">func generateRandomNumArray(numDigits: Int = 4) -> [Character] |
|||
{ |
|||
guard (1 ... 9).contains(numDigits) else { fatalError("number out of range") } |
|||
return Array("123456789".shuffled()[0 ..< numDigits]) |
|||
} |
|||
func parseGuess(_ guess: String, numDigits: Int = 4) -> String? |
|||
{ |
|||
guard guess.count == numDigits else { return nil } |
|||
// Only digits 0 to 9 allowed, no Unicode fractions or numbers from other languages |
|||
let guessArray = guess.filter{ $0.isASCII && $0.isWholeNumber } |
|||
guard Set(guessArray).count == numDigits else { return nil } |
|||
return guessArray |
|||
} |
|||
func pluralIfNeeded(_ count: Int, _ units: String) -> String |
|||
{ |
|||
return "\(count) " + units + (count == 1 ? "" : "s") |
|||
} |
|||
var guessAgain = "y" |
|||
while guessAgain == "y" |
|||
{ |
|||
let num = generateRandomNumArray() |
|||
var bulls = 0 |
|||
var cows = 0 |
|||
print("Please enter a 4 digit number with digits between 1-9, no repetitions: ") |
|||
if let guessStr = readLine(strippingNewline: true), let guess = parseGuess(guessStr) |
|||
{ |
|||
for (guess, actual) in zip(guess, num) |
|||
{ |
|||
if guess == actual |
|||
{ |
|||
bulls += 1 |
|||
} |
|||
else if num.contains(guess) |
|||
{ |
|||
cows += 1 |
|||
} |
|||
} |
|||
print("Actual number: " + num) |
|||
print("Your score: \(pluralIfNeeded(bulls, "bull")) and \(pluralIfNeeded(cows, "cow"))\n") |
|||
print("Would you like to play again? (y): ") |
|||
guessAgain = readLine(strippingNewline: true)?.lowercased() ?? "n" |
|||
} |
|||
else |
|||
{ |
|||
print("Invalid input") |
|||
} |
|||
} |
|||
</syntaxhighlight> |
|||
<syntaxhighlight lang="swift">import Foundation |
|||
func generateRandomNumArray(numDigits: Int = 4) -> [Int] { |
|||
guard numDigits > 0 else { |
|||
return [] |
|||
} |
|||
let needed = min(9, numDigits) |
|||
var nums = Set<Int>() |
|||
repeat { |
|||
nums.insert(.random(in: 1...9)) |
|||
} while nums.count != needed |
|||
return Array(nums) |
|||
} |
|||
func parseGuess(_ guess: String) -> [Int]? { |
|||
guard guess.count == 4 else { |
|||
return nil |
|||
} |
|||
let guessArray = guess.map(String.init).map(Int.init).compactMap({ $0 }) |
|||
guard Set(guessArray).count == 4 else { |
|||
return nil |
|||
} |
|||
return guessArray |
|||
} |
|||
while true { |
|||
let num = generateRandomNumArray() |
|||
var bulls = 0 |
|||
var cows = 0 |
|||
print("Please enter a 4 digit number with digits between 1-9, no repetitions: ") |
|||
guard let guessStr = readLine(strippingNewline: true), let guess = parseGuess(guessStr) else { |
|||
print("Invalid input") |
|||
continue |
|||
} |
|||
for (guess, actual) in zip(guess, num) { |
|||
if guess == actual { |
|||
bulls += 1 |
|||
} else if num.contains(guess) { |
|||
cows += 1 |
|||
} |
|||
} |
|||
print("Actual number: \(num.map(String.init).joined())") |
|||
print("Your score: \(bulls) bulls and \(cows) cows\n") |
|||
print("Would you like to play again? (y): ") |
|||
guard readLine(strippingNewline: true)!.lowercased() == "y" else { |
|||
exit(0) |
|||
} |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
<pre>Please enter a 4 digit number with digits between 1-9, no repetitions: |
|||
8496 |
|||
Actual number: 6475 |
|||
Your score: 1 bulls and 1 cows |
|||
Would you like to play again? (y): |
|||
y |
|||
Please enter a 4 digit number with digits between 1-9, no repetitions: |
|||
5983 |
|||
Actual number: 7846 |
|||
Your score: 0 bulls and 1 cows |
|||
</pre> |
|||
=={{header|Tcl}}== |
=={{header|Tcl}}== |
||
< |
<syntaxhighlight lang="tcl">proc main {} { |
||
fconfigure stdout -buffering none |
fconfigure stdout -buffering none |
||
set length 4 |
set length 4 |
||
Line 1,305: | Line 7,770: | ||
} |
} |
||
main</ |
main</syntaxhighlight> |
||
=={{header|Transd}}== |
|||
{{trans|C++}} |
|||
<syntaxhighlight lang="scheme">#lang transd |
|||
MainModule: { |
|||
contains-duplicates: (λ s String() -> Bool() |
|||
(with str String(s) (sort str) |
|||
(ret (neq (find-adjacent str) (end str)))) |
|||
), |
|||
play: (λ locals: |
|||
syms "0123456789" |
|||
len 4 |
|||
thenum String() |
|||
guess String() |
|||
(shuffle syms) |
|||
(= thenum (substr syms 0 len)) |
|||
(textout "Your guess: ") |
|||
(while (getline guess) |
|||
(if (eq guess "q") break) |
|||
(if (or (neq (size guess) len) |
|||
(neq (find-first-not-of guess syms) -1) |
|||
(contains-duplicates guess)) |
|||
(lout guess " is not valid guess") |
|||
(textout "Your guess: ") |
|||
continue |
|||
) |
|||
(with bulls 0 cows 0 pl 0 |
|||
(for i in Range(len) do |
|||
(= pl (index-of thenum (subn guess i))) |
|||
(if (eq pl i) (+= bulls 1) |
|||
elsif (neq pl -1) (+= cows 1)) |
|||
) |
|||
(lout "bulls: " bulls ", cows: " cows) |
|||
(if (eq bulls len) |
|||
(lout "Congratulations! You have found out the number!") |
|||
(ret null) |
|||
else (textout "Your guess: ")) |
|||
) |
|||
) |
|||
(lout "You quit the game.") |
|||
), |
|||
_start: (λ locals: s String() |
|||
(lout "Welcome to \"Bulls and cows\"!") |
|||
(while true |
|||
(while true |
|||
(textout "Do you want to play? (yes|no) : ") |
|||
(getline s) |
|||
(if (not (size s)) |
|||
(lout "Didn't receive an answer. Exiting.") (exit) |
|||
elsif (== (sub (tolower s) 0 1) "n") (lout "Bye!")(exit) |
|||
elsif (== (sub (tolower s) 0 1) "y") break |
|||
else (lout "(Hint: \"yes\" or \"no\".)")) |
|||
) |
|||
(play) |
|||
(lout "Another game?") |
|||
) |
|||
) |
|||
}</syntaxhighlight> |
|||
=={{header|TUSCRIPT}}== |
|||
<syntaxhighlight lang="tuscript"> |
|||
$$ MODE tuscript |
|||
SET nr1=RANDOM_NUMBERS (1,9,1) |
|||
LOOP |
|||
SET nr2=RANDOM_NUMBERS (1,9,1) |
|||
IF (nr2!=nr1) EXIT |
|||
ENDLOOP |
|||
LOOP |
|||
SET nr3=RANDOM_NUMBERS (1,9,1) |
|||
IF (nr3!=nr1,nr2) EXIT |
|||
ENDLOOP |
|||
LOOP |
|||
SET nr4=RANDOM_NUMBERS (1,9,1) |
|||
IF (nr4!=nr1,nr2,nr3) EXIT |
|||
ENDLOOP |
|||
SET nr=JOIN(nr1,"'",nr2,nr3,nr4), limit=10 |
|||
LOOP r=1,limit |
|||
SET bulls=cows=0 |
|||
ASK "round {r} insert a number":guessnr="" |
|||
SET length=LENGTH(guessnr), checknr=STRINGS (guessnr,":>/:") |
|||
LOOP n=nr,y=checknr |
|||
IF (length!=4) THEN |
|||
PRINT "4-letter digit required" |
|||
EXIT |
|||
ELSEIF (n==y) THEN |
|||
SET bulls=bulls+1 |
|||
ELSEIF (nr.ct.":{y}:") THEN |
|||
SET cows=cows+1 |
|||
ENDIF |
|||
ENDLOOP |
|||
PRINT "bulls=",bulls," cows=",cows |
|||
IF (bulls==4) THEN |
|||
PRINT "BINGO" |
|||
EXIT |
|||
ELSEIF (r==limit) THEN |
|||
PRINT "BETTER NEXT TIME" |
|||
EXIT |
|||
ENDIF |
|||
ENDLOOP |
|||
</syntaxhighlight> |
|||
Output: |
|||
<pre> |
|||
round 1 insert a number >1234 |
|||
bulls=1 cows=1 |
|||
round 2 insert a number >5678 |
|||
bulls=1 cows=1 |
|||
round 3 insert a number >1298 |
|||
bulls=2 cows=0 |
|||
round 4 insert a number >2379 |
|||
bulls=0 cows=0 |
|||
round 5 insert a number >1468 |
|||
bulls=4 cows=0 |
|||
BINGO |
|||
</pre> |
|||
=={{header|uBasic/4tH}}== |
|||
<syntaxhighlight lang="text">Local(2) ' Let's use no globals |
|||
Proc _Initialize ' Get our secret number |
|||
Do ' Repeat until it's guessed |
|||
Do |
|||
Input "Enter your guess: ";a@ ' Enter your guess |
|||
While FUNC(_Invalid(a@)) ' but make sure it's a valid guess |
|||
Loop |
|||
a@ = FUNC(_Bulls) ' Count the number of bulls |
|||
b@ = FUNC(_Cows) ' Count the number of cows |
|||
' Now give some feedback |
|||
Print : Print "\tThere were ";a@;" bulls and ";b@;" cows." : Print |
|||
Until a@ = 4 ' Until the secret is guessed |
|||
Loop |
|||
Print "You win!" ' Yes, you guessed it |
|||
End |
|||
_Initialize ' Make a secret |
|||
Local (1) |
|||
Do |
|||
a@ = 1234 + RND(8643) ' Get a valid number |
|||
While FUNC(_Invalid(a@)) ' and accept it unless invalid |
|||
Loop |
|||
For a@ = 0 to 3 ' Now save it at the proper place |
|||
@(a@+4) = @(a@) |
|||
Next |
|||
Return |
|||
_Invalid Param(1) ' Check whether a number is valid |
|||
Local(2) |
|||
' Ok, these can't be right at all |
|||
If (a@ < 1234) + (a@ > 9876) Then Return (1) |
|||
' Now break 'em up in different digits |
|||
For b@ = 3 To 0 Step -1 |
|||
@(b@) = a@ % 10 ' A digit of zero can't be right |
|||
If @(b@) = 0 Then Unloop : Return (1) |
|||
a@ = a@ / 10 |
|||
Next |
|||
For b@ = 0 To 2 ' Now compare all digits |
|||
For c@ = b@ + 1 To 3 ' The others were already compared |
|||
If @(b@) = @(c@) Then Unloop : Unloop : Return (1) |
|||
Next ' Wrong, we found similar digits |
|||
Next |
|||
Return (0) ' All digits are different |
|||
_Bulls ' Count the number of valid guesses |
|||
Local (2) |
|||
b@ = 0 ' Start with zero |
|||
For a@ = 0 to 3 ' Increment with each valid guess |
|||
If @(a@) = @(a@+4) Then b@ = b@ + 1 |
|||
Next |
|||
Return (b@) ' Return number of valid guesses |
|||
_Cows |
|||
Local (3) ' Count the number of proper digits |
|||
c@ = 0 ' Start with zero |
|||
For a@ = 0 To 3 ' All the players guesses |
|||
For b@ = 4 To 7 ' All the computers secrets |
|||
If (a@+4) = b@ Then Continue ' Skip the bulls |
|||
If @(a@) = @(b@) Then c@ = c@ + 1 |
|||
Next ' Increment with valid digits |
|||
Next |
|||
Return (c@) ' Return number of valid digits</syntaxhighlight> |
|||
The addition of strings allows for much simpler code. |
|||
<syntaxhighlight lang="text">Do |
|||
s = Str(1234 + RND(8643)) |
|||
Until FUNC(_Check(s)) |
|||
Next |
|||
Do |
|||
Do |
|||
g = Ask("Enter your guess: ") |
|||
If (Val(g) = Info("nil")) + (Len(g) # 4) Then Continue |
|||
Until FUNC(_Check(g)) |
|||
Loop |
|||
b = 0 : c = 0 |
|||
For i = 0 To 3 |
|||
For j = 0 to 3 |
|||
If Peek(s, i) = Peek(g, j) Then |
|||
If i = j Then |
|||
b = b + 1 |
|||
Else |
|||
c = c + 1 |
|||
EndIf |
|||
EndIf |
|||
Next |
|||
Next |
|||
Print "You scored ";b;" bulls and ";c; " cows.\n" |
|||
Until b = 4 |
|||
Loop |
|||
End |
|||
_Check |
|||
Param (1) |
|||
Local (2) |
|||
b@ = 0 |
|||
For c@ = 0 To 3 |
|||
If Peek(a@, c@) = Ord ("0") Then Unloop : Return (0) |
|||
If And(b@, 2^(Peek(a@, c@) - Ord ("0"))) Then Unloop : Return (0) |
|||
b@ = b@ + 2^(Peek(a@, c@) - Ord ("0")) |
|||
Next |
|||
Return (1)</syntaxhighlight> |
|||
=={{header|UNIX Shell}}== |
|||
{{works with|bash|3}} |
|||
<syntaxhighlight lang="bash">#!/bin/bash |
|||
rand() { |
|||
local min=${1:-0} |
|||
local max=${2:-32767} |
|||
[ ${min} -gt ${max} ] && |
|||
min=$(( min ^ max )) && |
|||
max=$(( min ^ max )) && |
|||
min=$(( min ^ max )) |
|||
echo -n $(( ( $RANDOM % $max ) + $min )) |
|||
} |
|||
in_arr() { |
|||
local quandry="${1}" |
|||
shift |
|||
local arr=( $@ ) |
|||
local i='' |
|||
for i in ${arr[*]} |
|||
do |
|||
[ "${quandry}" == "${i}" ] && return 0 && break |
|||
done |
|||
return 1 |
|||
} |
|||
delete_at() { |
|||
local idx="$(( $1 + 1 ))" |
|||
shift |
|||
local arr=( "sentinel" $@ ) |
|||
echo -n "${arr[@]:1:$(( idx - 1 ))} ${arr[@]:$((idx + 1)):$(( ${#arr[@]} - idx - 1))}" |
|||
} |
|||
delete_first() { |
|||
local meanie="${1}" |
|||
shift |
|||
local arr=( $@ ) |
|||
local i=0 |
|||
for (( i = 0; i < ${#arr[@]} ; i++ )) |
|||
do |
|||
[ "${arr[${i}]}" == "${meanie}" ] && arr=( $( delete_at ${i} ${arr[*]} ) ) |
|||
done |
|||
echo -n "${arr[*]}" |
|||
} |
|||
to_arr() { |
|||
local string="${1}" |
|||
local arr=() |
|||
while [ "${#string}" -gt 0 ] |
|||
do |
|||
arr=( ${arr[*]} ${string:0:1} ) |
|||
string="${string:1}" |
|||
done |
|||
echo -n "${arr[*]}" |
|||
} |
|||
choose_idx() { |
|||
local arr=( $@ ) |
|||
echo -n "$( rand 0 $(( ${#arr[@]} - 1 )) )" |
|||
} |
|||
locate_bulls() { |
|||
local secret=( $( to_arr "${1}" ) ) |
|||
local guess=( $( to_arr "${2}" ) ) |
|||
local hits=() |
|||
local i=0 |
|||
for (( i=0; i<4; i++ )) |
|||
do |
|||
[ "${secret[${i}]}" -eq "${guess[${i}]}" ] && hits=( ${hits[*]} ${i} ) |
|||
done |
|||
echo -n "${hits[*]}" |
|||
} |
|||
bulls() { |
|||
local secret="${1}" |
|||
local guess="${2}" |
|||
local bulls=( $( locate_bulls "${secret}" "${guess}" ) ) |
|||
echo -n "${#bulls[@]}" |
|||
} |
|||
cows() { |
|||
local secret=( $( to_arr "${1}" ) ) |
|||
local guess=( $( to_arr "${2}" ) ) |
|||
local bulls=( $( locate_bulls "${1}" "${2}" ) ) |
|||
local hits=0 |
|||
local i='' |
|||
# Avoid double-counting bulls |
|||
for i in ${bulls[*]} |
|||
do |
|||
secret=( $( delete_at ${i} ${secret[*]} ) ) |
|||
done |
|||
# Process the guess against what's left of the secret |
|||
for i in ${guess[*]} |
|||
do |
|||
in_arr "${i}" ${secret[*]} && |
|||
secret=( $( delete_first "${i}" ${secret[*]} ) ) && |
|||
(( hits++ )) |
|||
done |
|||
echo -n ${hits} |
|||
} |
|||
malformed() { |
|||
local guess=( $( to_arr "${1}" ) ) |
|||
local i='' |
|||
[ ${#guess[@]} -ne 4 ] && |
|||
return 0 |
|||
for i in ${guess[*]} |
|||
do |
|||
if ! in_arr ${i} 1 2 3 4 5 6 7 8 9 |
|||
then |
|||
return 0 |
|||
break |
|||
fi |
|||
done |
|||
return 1 |
|||
} |
|||
candidates=( 1 2 3 4 5 6 7 8 9 ) |
|||
secret='' |
|||
while [ "${#secret}" -lt 4 ] |
|||
do |
|||
cidx=$( choose_idx ${candidates[*]} ) |
|||
secret="${secret}${candidates[${cidx}]}" |
|||
candidates=( $(delete_at ${cidx} ${candidates[*]} ) ) |
|||
done |
|||
while read -p "Enter a four-digit guess: " guess |
|||
do |
|||
malformed "${guess}" && echo "Malformed guess" && continue |
|||
[ "${guess}" == "${secret}" ] && echo "You win!" && exit |
|||
echo "Score: $( bulls "${secret}" "${guess}" ) Bulls, $( cows "${secret}" "${guess}" ) Cows" |
|||
done</syntaxhighlight> |
|||
=={{header|VBA}}== |
|||
<syntaxhighlight lang="vb"> |
|||
Option Explicit |
|||
Sub Main_Bulls_and_cows() |
|||
Dim strNumber As String, strInput As String, strMsg As String, strTemp As String |
|||
Dim boolEnd As Boolean |
|||
Dim lngCpt As Long |
|||
Dim i As Byte, bytCow As Byte, bytBull As Byte |
|||
Const NUMBER_OF_DIGITS As Byte = 4 |
|||
Const MAX_LOOPS As Byte = 25 'the max of lines supported by MsgBox |
|||
strNumber = Create_Number(NUMBER_OF_DIGITS) |
|||
Do |
|||
bytBull = 0: bytCow = 0: lngCpt = lngCpt + 1 |
|||
If lngCpt > MAX_LOOPS Then strMsg = "Max of loops... Sorry you loose!": Exit Do |
|||
strInput = AskToUser(NUMBER_OF_DIGITS) |
|||
If strInput = "Exit Game" Then strMsg = "User abort": Exit Do |
|||
For i = 1 To Len(strNumber) |
|||
If Mid(strNumber, i, 1) = Mid(strInput, i, 1) Then |
|||
bytBull = bytBull + 1 |
|||
ElseIf InStr(strNumber, Mid(strInput, i, 1)) > 0 Then |
|||
bytCow = bytCow + 1 |
|||
End If |
|||
Next i |
|||
If bytBull = Len(strNumber) Then |
|||
boolEnd = True: strMsg = "You win in " & lngCpt & " loops!" |
|||
Else |
|||
strTemp = strTemp & vbCrLf & "With : " & strInput & " ,you have : " & bytBull & " bulls," & bytCow & " cows." |
|||
MsgBox strTemp |
|||
End If |
|||
Loop While Not boolEnd |
|||
MsgBox strMsg |
|||
End Sub |
|||
Function Create_Number(NbDigits As Byte) As String |
|||
Dim myColl As New Collection |
|||
Dim strTemp As String |
|||
Dim bytAlea As Byte |
|||
Randomize |
|||
Do |
|||
bytAlea = Int((Rnd * 9) + 1) |
|||
On Error Resume Next |
|||
myColl.Add CStr(bytAlea), CStr(bytAlea) |
|||
If Err <> 0 Then |
|||
On Error GoTo 0 |
|||
Else |
|||
strTemp = strTemp & CStr(bytAlea) |
|||
End If |
|||
Loop While Len(strTemp) < NbDigits |
|||
Create_Number = strTemp |
|||
End Function |
|||
Function AskToUser(NbDigits As Byte) As String |
|||
Dim boolGood As Boolean, strIn As String, i As Byte, NbDiff As Byte |
|||
Do While Not boolGood |
|||
strIn = InputBox("Enter your number (" & NbDigits & " digits)", "Number") |
|||
If StrPtr(strIn) = 0 Then strIn = "Exit Game": Exit Do |
|||
If strIn <> "" Then |
|||
If Len(strIn) = NbDigits Then |
|||
NbDiff = 0 |
|||
For i = 1 To Len(strIn) |
|||
If Len(Replace(strIn, Mid(strIn, i, 1), "")) < NbDigits - 1 Then |
|||
NbDiff = 1 |
|||
Exit For |
|||
End If |
|||
Next i |
|||
If NbDiff = 0 Then boolGood = True |
|||
End If |
|||
End If |
|||
Loop |
|||
AskToUser = strIn |
|||
End Function |
|||
</syntaxhighlight> |
|||
=={{header|VBScript}}== |
|||
VBS functions return variants. I use t to return a single error value or a pair bulls, cows on result<br /> |
|||
VBS does'nt have a continue so i used the classic do loop inside do loop in the main program |
|||
<syntaxhighlight lang="vb"> |
|||
randomize timer |
|||
fail=array("Wrong number of chars","Only figures 0 to 9 allowed","Two or more figures are the same") |
|||
p=dopuzzle() |
|||
wscript.echo "Bulls and Cows. Guess my 4 figure number!" |
|||
do |
|||
do |
|||
wscript.stdout.write vbcrlf & "your move ": s=trim(wscript.stdin.readline) |
|||
c=checkinput(s) |
|||
if not isarray (c) then wscript.stdout.write fail(c) :exit do |
|||
bu=c(0) |
|||
wscript.stdout.write "bulls: " & c(0) & " | cows: " & c(1) |
|||
loop while 0 |
|||
loop until bu=4 |
|||
wscript.stdout.write vbcrlf & "You won! " |
|||
function dopuzzle() |
|||
dim b(10) |
|||
for i=1 to 4 |
|||
do |
|||
r=fix(rnd*10) |
|||
loop until b(r)=0 |
|||
b(r)=1:dopuzzle=dopuzzle+chr(r+48) |
|||
next |
|||
end function |
|||
function checkinput(s) |
|||
dim c(10) |
|||
bu=0:co=0 |
|||
if len(s)<>4 then checkinput=0:exit function |
|||
for i=1 to 4 |
|||
b=mid(s,i,1) |
|||
if instr("0123456789",b)=0 then checkinput=1 :exit function |
|||
if c(asc(b)-48)<>0 then checkinput=2 :exit function |
|||
c(asc(b)-48)=1 |
|||
for j=1 to 4 |
|||
if asc(b)=asc(mid(p,j,1)) then |
|||
if i=j then bu=bu+1 else co=co+1 |
|||
end if |
|||
next |
|||
next |
|||
checkinput=array(bu,co) |
|||
end function |
|||
</syntaxhighlight> |
|||
=={{header|Vedit macro language}}== |
=={{header|Vedit macro language}}== |
||
<syntaxhighlight lang="vedit">Buf_Switch(Buf_Free) |
|||
<lang vedit> |
|||
Buf_Switch(Buf_Free) |
|||
#90 = Time_Tick // seed for random number generator |
#90 = Time_Tick // seed for random number generator |
||
#91 = 10 // random numbers in range 0 to 9 |
#91 = 10 // random numbers in range 0 to 9 |
||
Line 1,355: | Line 8,338: | ||
#93 = 0x7fffffff % 48271 |
#93 = 0x7fffffff % 48271 |
||
#90 = (48271 * (#90 % #92) - #93 * (#90 / #92)) & 0x7fffffff |
#90 = (48271 * (#90 % #92) - #93 * (#90 / #92)) & 0x7fffffff |
||
Return ((#90 & 0xffff) * #91 / 0x10000) |
Return ((#90 & 0xffff) * #91 / 0x10000)</syntaxhighlight> |
||
</lang> |
|||
=={{header|Visual Basic .NET}}== |
=={{header|Visual Basic .NET}}== |
||
< |
<syntaxhighlight lang="vbnet">Imports System |
||
Imports System.Text.RegularExpressions |
Imports System.Text.RegularExpressions |
||
Line 1,415: | Line 8,396: | ||
Console.WriteLine("The number was guessed in {0} attempts. Congratulations!", attempt) |
Console.WriteLine("The number was guessed in {0} attempts. Congratulations!", attempt) |
||
End Sub |
End Sub |
||
End Module |
End Module</syntaxhighlight> |
||
</lang> |
|||
=={{header|V (Vlang)}}== |
|||
<syntaxhighlight lang="v (vlang)"> |
|||
import rand |
|||
import os |
|||
fn main() { |
|||
valid := ['1','2','3','4','5','6','7','8','9'] |
|||
mut value := []string{} |
|||
mut guess, mut elem := '', '' |
|||
mut cows, mut bulls := 0, 0 |
|||
println('Cows and Bulls') |
|||
println('Guess four digit numbers of unique digits in the range 1 to 9.') |
|||
println('A correct digit, but not in the correct place is a cow.') |
|||
println('A correct digit, and in the correct place is a bull.') |
|||
// generate pattern |
|||
for value.len < 4 { |
|||
elem = rand.string_from_set('123456789', 1) |
|||
if value.any(it == elem) == false { |
|||
value << elem |
|||
} |
|||
} |
|||
// start game |
|||
input: for _ in 0..3 { |
|||
guess = os.input('Guess: ').str() |
|||
// deal with malformed guesses |
|||
if guess.len != 4 {println('Please input a four digit number.') continue input} |
|||
for val in guess { |
|||
if valid.contains(val.ascii_str()) == false { |
|||
{println('Please input a number between 1 to 9.') continue input} |
|||
} |
|||
if guess.count(val.ascii_str()) > 1 { |
|||
{println('Please do not repeat the same digit.') continue input} |
|||
} |
|||
} |
|||
// score guesses |
|||
for idx, gval in guess { |
|||
match true { |
|||
gval.ascii_str() == value[idx] { |
|||
bulls++ |
|||
println('${gval.ascii_str()} was correctly guessed, and in the correct location! ') |
|||
} |
|||
gval.ascii_str() in value { |
|||
cows++ |
|||
println('${gval.ascii_str()} was correctly quessed, but not in the exact location! ') |
|||
} |
|||
else {} |
|||
} |
|||
if bulls == 4 {println('You are correct and have won!!! Congratulations!!!') exit(0)} |
|||
} |
|||
println('score: bulls: $bulls cows: $cows') |
|||
} |
|||
println('Only 3 guesses allowed. The correct value was: $value') |
|||
println('Sorry, you lost this time, try again.') |
|||
} |
|||
</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Cows and Bulls |
|||
Guess four digit numbers of unique digits in the range 1 to 9. |
|||
A correct digit, but not in the correct place is a cow. |
|||
A correct digit, and in the correct place is a bull. |
|||
Guess: 2673 |
|||
6 was correctly quessed, but not in the exact location! |
|||
score: bulls: 0 cows: 1 |
|||
Guess: 1658 |
|||
6 was correctly quessed, but not in the exact location! |
|||
5 was correctly quessed, but not in the exact location! |
|||
8 was correctly quessed, but not in the exact location! |
|||
score: bulls: 0 cows: 4 |
|||
Guess: 6859 |
|||
6 was correctly quessed, but not in the exact location! |
|||
8 was correctly guessed, and in the correct location! |
|||
5 was correctly quessed, but not in the exact location! |
|||
score: bulls: 1 cows: 6 |
|||
Only 3 guesses allowed. The correct value was: ['5', '8', '4', '6'] |
|||
Sorry, you lost this time, try again. |
|||
</pre> |
|||
=={{header|VTL-2}}== |
|||
<syntaxhighlight lang="VTL2">10 I=1 |
|||
20 J=1 |
|||
30 :I)='/10*0+% |
|||
40 #=:I)=0*30+(0<:I)*70 |
|||
50 #=:I)=:J)*20 |
|||
60 J=J+1 |
|||
70 #=J<I*50 |
|||
80 I=I+1 |
|||
90 #=4>I*20 |
|||
100 ?="BULLS AND COWS" |
|||
110 ?="--------------" |
|||
120 ?="" |
|||
125 T=0 |
|||
130 T=T+1 |
|||
140 ?="GUESS? "; |
|||
150 G=? |
|||
160 #=G<1234+(G>9877)*510 |
|||
170 I=8 |
|||
180 G=G/10 |
|||
190 :I)=% |
|||
200 I=I-1 |
|||
210 #=4<I*180 |
|||
220 #=:5)*:6)*:7)*:8)=0*510 |
|||
230 I=6 |
|||
240 J=5 |
|||
250 #=:I)=:J)*510 |
|||
260 J=J+1 |
|||
270 #=J<I*250 |
|||
280 I=I+1 |
|||
290 #=I<9*240 |
|||
300 B=0 |
|||
310 C=0 |
|||
320 I=1 |
|||
330 B=:I)=:I+4)+B |
|||
340 J=1 |
|||
350 C=(I=J=0)*(:I)=:J+4))+C |
|||
360 J=J+1 |
|||
370 #=4>J*350 |
|||
380 I=I+1 |
|||
390 #=4>I*330 |
|||
400 ?="BULLS: "; |
|||
410 ?=B |
|||
420 ?=", COWS: "; |
|||
430 ?=C |
|||
440 ?="" |
|||
450 #=B<4*130 |
|||
460 ?="" |
|||
470 ?="YOU GOT IT IN "; |
|||
480 ?=T |
|||
490 ?=" TRIES!" |
|||
500 #=1000 |
|||
510 ?="BAD GUESS - GUESS NEEDS TO BE 4 UNIQUE DIGITS WITHOUT ZEROES" |
|||
520 #=140</syntaxhighlight> |
|||
{{out}} |
|||
<pre>BULLS AND COWS |
|||
-------------- |
|||
GUESS? 1234 |
|||
BULLS: 0, COWS: 1 |
|||
GUESS? 5678 |
|||
BULLS: 0, COWS: 2 |
|||
GUESS? 1978 |
|||
BULLS: 1, COWS: 2 |
|||
GUESS? 2978 |
|||
BULLS: 1, COWS: 2 |
|||
GUESS? 3978 |
|||
BULLS: 1, COWS: 2 |
|||
GUESS? 4978 |
|||
BULLS: 1, COWS: 3 |
|||
GUESS? 7984 |
|||
BULLS: 1, COWS: 3 |
|||
GUESS? 8947 |
|||
BULLS: 4, COWS: 0 |
|||
YOU GOT IT IN 8 TRIES!</pre> |
|||
=={{header|Wren}}== |
|||
{{trans|Kotlin}} |
|||
{{libheader|Wren-set}} |
|||
{{libheader|Wren-ioutil}} |
|||
<syntaxhighlight lang="wren">import "random" for Random |
|||
import "./set" for Set |
|||
import "./ioutil" for Input |
|||
var MAX_GUESSES = 20 // say |
|||
var r = Random.new() |
|||
var num |
|||
// generate a 4 digit random number from 1234 to 9876 with no zeros or repeated digits |
|||
while (true) { |
|||
num = (1234 + r.int(8643)).toString |
|||
if (!num.contains("0") && Set.new(num).count == 4) break |
|||
} |
|||
System.print("All guesses should have exactly 4 distinct digits excluding zero.") |
|||
System.print("Keep guessing until you guess the chosen number (maximum %(MAX_GUESSES) valid guesses).\n") |
|||
var guesses = 0 |
|||
while (true) { |
|||
var guess = Input.text("Enter your guess : ") |
|||
if (guess == num) { |
|||
System.print("You've won with %(guesses+1) valid guesses!") |
|||
return |
|||
} |
|||
var n = Num.fromString(guess) |
|||
if (!n) { |
|||
System.print("Not a valid number") |
|||
} else if (guess.contains("-") || guess.contains("+") || guess.contains(".")) { |
|||
System.print("Can't contain a sign or decimal point") |
|||
} else if (guess.contains("e") || guess.contains("E")) { |
|||
System.print("Can't contain an exponent") |
|||
} else if (guess.contains("0")) { |
|||
System.print("Can't contain zero") |
|||
} else if (guess.count != 4) { |
|||
System.print("Must have exactly 4 digits") |
|||
} else if (Set.new(guess).count < 4) { |
|||
System.print("All digits must be distinct") |
|||
} else { |
|||
var bulls = 0 |
|||
var cows = 0 |
|||
var i = 0 |
|||
for (c in guess) { |
|||
if (num[i] == c) { |
|||
bulls = bulls + 1 |
|||
} else if (num.contains(c)) { |
|||
cows = cows + 1 |
|||
} |
|||
i = i + 1 |
|||
} |
|||
System.print("Your score for this guess: Bulls = %(bulls) Cows = %(cows)") |
|||
guesses = guesses + 1 |
|||
if (guesses == MAX_GUESSES) { |
|||
System.print("You've now had %(guesses) valid guesses, the maximum allowed") |
|||
return |
|||
} |
|||
} |
|||
}</syntaxhighlight> |
|||
{{out}} |
|||
Sample game: |
|||
<pre> |
|||
All guesses should have exactly 4 distinct digits excluding zero. |
|||
Keep guessing until you guess the chosen number (maximum 20 valid guesses). |
|||
Enter your guess : 1234 |
|||
Your score for this guess: Bulls = 1 Cows = 1 |
|||
Enter your guess : 1567 |
|||
Your score for this guess: Bulls = 0 Cows = 1 |
|||
Enter your guess : 8239 |
|||
Your score for this guess: Bulls = 2 Cows = 1 |
|||
Enter your guess : 8294 |
|||
Your score for this guess: Bulls = 2 Cows = 0 |
|||
Enter your guess : 8273 |
|||
Your score for this guess: Bulls = 3 Cows = 0 |
|||
Enter your guess : 8275 |
|||
Your score for this guess: Bulls = 2 Cows = 1 |
|||
Enter your guess : 8263 |
|||
Your score for this guess: Bulls = 3 Cows = 0 |
|||
Enter your guess : 8213 |
|||
Your score for this guess: Bulls = 3 Cows = 0 |
|||
Enter your guess : 8253 |
|||
You've won with 9 valid guesses! |
|||
</pre> |
|||
=={{header|XPL0}}== |
|||
<syntaxhighlight lang "XPL0">int Bulls, Cows, Secret(4), Guess(4), Guesses, Used, I, J, Done, Digit, Okay; |
|||
[Used:= 0; \generate secret random number using digits |
|||
for I:= 0 to 3 do \ 1 to 9 without any repeated digits |
|||
[repeat Digit:= Ran(9)+1; |
|||
until (Used & 1<<Digit) = 0; |
|||
Used:= Used ! 1<<Digit; |
|||
Secret(I):= Digit + ^0; |
|||
]; |
|||
Text(0, "Guess the secret number.^m^j"); |
|||
Text(0, "Guesses must be four different digits, 1 to 9.^m^j"); |
|||
Guesses:= 0; |
|||
loop [Done:= false; \main game loop |
|||
repeat Text(0, "Enter your guess: "); \get valid 4-digits from player |
|||
OpenI(0); Used:= 0; I:= 0; |
|||
loop [Digit:= ChIn(0); |
|||
Okay:= Digit>=^1 and Digit<=^9; |
|||
Digit:= Digit & $0F; \convert ASCII to binary |
|||
if not Okay or Used & 1<<Digit then |
|||
[Text(0, |
|||
"Please enter four distinct digits, 1 thru 9.^m^j"); |
|||
quit; |
|||
]; |
|||
Guess(I):= Digit + ^0; |
|||
Used:= Used ! 1<<Digit; |
|||
I:= I+1; |
|||
if I = 4 then [Done:= true; quit]; |
|||
]; |
|||
until Done; |
|||
Guesses:= Guesses+1; |
|||
Bulls:= 0; Cows:= 0; |
|||
for I:= 0 to 3 do |
|||
for J:= 0 to 3 do |
|||
if Guess(I) = Secret(J) then |
|||
if I=J then Bulls:= Bulls+1 |
|||
else Cows:= Cows+1; |
|||
Text(0, "Bulls: "); IntOut(0, Bulls); |
|||
Text(0, " Cows: "); IntOut(0, Cows); |
|||
CrLf(0); |
|||
if Bulls = 4 then quit; |
|||
]; |
|||
Text(0, "Congratulations! You won in "); IntOut(0, Guesses); |
|||
Text(0, " guesses.^m^j"); |
|||
]</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
Guess the secret number. |
|||
Guesses must be four different digits, 1 to 9. |
|||
Enter your guess: 1234 |
|||
Bulls: 1 Cows: 1 |
|||
Enter your guess: 3345 |
|||
Please enter four distinct digits, 1 thru 9. |
|||
Enter your guess: 0987 |
|||
Please enter four distinct digits, 1 thru 9. |
|||
Enter your guess: 1357 |
|||
Bulls: 1 Cows: 0 |
|||
Enter your guess: |
|||
</pre> |
|||
=={{header|zkl}}== |
|||
Play one game: |
|||
<syntaxhighlight lang="zkl">d:=Dictionary(); do{ d[(1).random(10)]=True }while(d.len()<4); |
|||
abcd:=d.keys.shuffle(); |
|||
while(1){ |
|||
guess:=ask("4 digits: ")-" ,"; |
|||
if(guess.len()!=4 or guess.unique().len()!=4) continue; |
|||
bulls:=abcd.zipWith('==,guess).sum(0); |
|||
cows:=guess.split("").enumerate() |
|||
.reduce('wrap(s,[(n,c)]){ s + (d.find(c,False) and abcd[n]!=c) },0); |
|||
if(bulls==4) { println("You got it!"); break; } |
|||
"%d bull%s and %d cow%s".fmt(bulls,s(bulls),cows,s(cows)).println(); |
|||
} |
|||
fcn s(n){ (n!=1) and "s" or "" }</syntaxhighlight> |
|||
{{out}} |
|||
<pre> |
|||
4 digits: 4,5,6,7 |
|||
1 bull and 0 cows |
|||
4 digits: 1234 |
|||
0 bulls and 2 cows |
|||
4 digits: 3528 |
|||
You got it! |
|||
</pre> |
Latest revision as of 16:13, 7 August 2024
![Task](http://static.miraheze.org/rosettacodewiki/thumb/b/ba/Rcode-button-task-crushed.png/64px-Rcode-button-task-crushed.png)
You are encouraged to solve this task according to the task description, using any language you may know.
Bulls and Cows is an old game played with pencil and paper that was later implemented using computers.
- 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
8080 Assembly
This is written to run under CP/M and includes an RNG to generate the secret.
bdos equ 5
putchar equ 2
rawio equ 6
puts equ 9
cstat equ 11
reads equ 10
org 100h
mvi c,puts
lxi d,signon ; Print name
call bdos
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Initialize the RNG with keyboard input
mvi c,puts
lxi d,entropy ; Ask for randomness
call bdos
mvi b,9 ; 9 times,
randloop: mvi c,3 ; read 3 keys.
lxi h,xabcdat + 1
randkey: push b ; Read a key
push h
randkeywait: mvi c,rawio
mvi e,0FFh
call bdos
ana a
jz randkeywait
pop h
pop b
xra m ; XOR it with the random memory
mov m,a
inx h
dcr c
jnz randkey ; Go get more characters
dcr b
jnz randloop
mvi c,puts
lxi d,done ; Tell the user we're done
call bdos
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Generate 4-digit secret code
lxi h,secret
mvi b,4
gencode: push h
push b
call randcode
pop b
pop h
mov m,a
inx h
dcr b
jnz gencode
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; User makes a guess
readguess: mvi c,puts ; Ask for guess
lxi d,guess
call bdos
mvi c,reads ; Read guess
lxi d,bufdef
call bdos
call newline ; Print newline
mvi b,4 ; Check input
lxi h,buf
validate: mov a,m
cpi '9' + 1 ; >9?
jnc inval ; = invalid
cpi '1' ; <1?
jc inval ; = invalid
sui '0' ; Make ASCII digit into number
mov m,a
inx h
dcr b
jnz validate
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Count bulls
mvi c,puts
lxi d,bulls ; Output "Bulls:"
call bdos
lxi d,secret
lxi h,buf
lxi b,4 ; No bulls, counter = 4
bullloop: ldax d ; Get secret digit
cmp m ; Match to buffer digit
cz countmatch
inx h
inx d
dcr c
jnz bullloop
push b ; Keep bulls for cow count,
push b ; and for final check.
call printcount
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Count cows
mvi c,puts
lxi d,cows ; Output ", Cows:"
call bdos
pop psw ; Retrieve the bulls (into A reg)
cma ; Negate amount of bulls
inr a
mov b,a ; Use it as start of cow count
mvi d,4 ; For all 4 secret digits..
lxi h,secret
cowouter: mov a,m ; Grab secret digit to test
push h ; Store secret position
mvi e,4 ; For all 4 input digits...
lxi h,buf
cowinner: cmp m ; Compare to current secret digit
cz countmatch
inx h
dcr e ; While there are more digits in buf
jnz cowinner ; Test next digit
pop h ; Restore secret position
inx h ; Look at next secret digit
dcr d ; While there are digits left
jnz cowouter
push b ; Keep cow count
call printcount
call newline
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Check win condition
pop psw ; Cow count (in A)
pop b ; Bull count (in B)
ana a ; To win, there must be 0 cows...
jnz readguess
mvi a,4 ; And 4 bulls.
cmp b
jnz readguess
mvi c,puts
lxi d,win
jmp bdos
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Increment bull/cow counter
countmatch: inr b
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Print a newline
newline: mvi c,puts
lxi d,nl
jmp bdos
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Output counter as ASCII
printcount: mvi a,'0'
add b
mvi c,putchar
mov e,a
jmp bdos
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; User entered invalid input
inval: mvi c,puts
lxi d,invalid
call bdos
jmp readguess
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Generate random number 1-9 that isn't in key
randcode: call xabcrand
ani 0fh ; Low nybble
ana a ; 0 = invalid
jz randcode
cpi 10 ; >9 = invalid
jnc randcode
;; Check if it is a duplicate
mvi b,4
lxi h,secret
checkdup: cmp m
jz randcode
inx h
dcr b
jnz checkdup
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; The "X ABC" 8-bit random number generator
;; (Google that to find where it came from)
xabcrand: lxi h,xabcdat
inr m ; X++
mov a,m ; X,
inx h ;
xra m ; ^ C,
inx h ;
xra m ; ^ A,
mov m,a ; -> A
inx h
add m ; + B,
mov m,a ; -> B
rar ; >>1
dcx h
xra m ; ^ A,
dcx h
add m ; + C
mov m,a ; -> C
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Strings
signon: db 'Bulls and Cows',13,10,'$'
entropy: db 'Please mash the keyboard to generate entropy...$'
done: db 'done.',13,10,13,10,'$'
bulls: db 'Bulls: $'
cows: db ', Cows: $'
guess: db 'Guess: $'
invalid: db 'Invalid input.',13,10,'$'
win: db 'You win!',13,10,'$'
nl: db 13,10,'$'
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Variables
xabcdat: ds 4 ; RNG state
secret: ds 4 ; Holds the secret code
bufdef: db 4,0 ; User input buffer
buf: ds 4
ABC
HOW TO RETURN random.digit:
RETURN choice "123456789"
HOW TO MAKE SECRET secret:
PUT "" IN secret
FOR i IN {1..4}:
PUT random.digit IN digit
WHILE SOME j IN {1..i-1} HAS secret item j = digit:
PUT random.digit IN digit
PUT secret^digit IN secret
HOW TO RETURN guess count.bulls secret:
PUT 0 IN bulls
FOR i IN {1..4}:
IF secret item i = guess item i: PUT bulls+1 IN bulls
RETURN bulls
HOW TO RETURN guess count.cows secret:
PUT -(guess count.bulls secret) IN cows
FOR c IN guess:
IF c in secret: PUT cows+1 IN cows
RETURN cows
HOW TO REPORT has.duplicates guess:
FOR i IN {1..3}:
FOR j IN {i+1..4}:
IF guess item i = guess item j: SUCCEED
FAIL
HOW TO REPORT is.valid guess:
IF SOME digit IN guess HAS digit not.in "123456789":
WRITE "Invalid digit: ", digit/
FAIL
IF #guess <> 4:
WRITE "Guess must contain 4 digits."/
FAIL
IF has.duplicates guess:
WRITE "No duplicates allowed"/
FAIL
SUCCEED
HOW TO READ GUESS guess:
WHILE 1=1:
WRITE "Guess? "
READ guess RAW
IF is.valid guess: QUIT
HOW TO PLAY BULLS AND COWS:
PUT 0, 0, 0 IN tries, bulls, cows
MAKE SECRET secret
WRITE "Bulls and cows"/
WRITE "--------------"/
WRITE /
WHILE bulls<>4:
READ GUESS guess
PUT guess count.bulls secret IN bulls
PUT guess count.cows secret IN cows
WRITE "Bulls:",bulls,"- Cows:",cows/
PUT tries+1 IN tries
WRITE "You win! Tries:", tries
PLAY BULLS AND COWS
- Output:
Bulls and cows -------------- Guess? 1234 Bulls: 0 - Cows: 1 Guess? 5678 Bulls: 0 - Cows: 2 Guess? 1679 Bulls: 0 - Cows: 2 Guess? 1689 Bulls: 0 - Cows: 2 Guess? 1659 Bulls: 1 - Cows: 2 Guess? 2659 Bulls: 1 - Cows: 2 Guess? 3659 Bulls: 1 - Cows: 3 Guess? 9356 Bulls: 4 - Cows: 0 You win! Tries: 8
Action!
DEFINE DIGNUM="4"
TYPE Score=[BYTE bulls,cows,err]
PROC Generate(CHAR ARRAY secret)
DEFINE DIGCOUNT="9"
CHAR ARRAY digits(DIGCOUNT)
BYTE i,j,d,tmp,count
FOR i=0 TO DIGCOUNT-1
DO
digits(i)=i+'1
OD
secret(0)=DIGNUM
count=DIGCOUNT
FOR i=1 TO DIGNUM
DO
d=Rand(count)
secret(i)=digits(d)
count==-1
digits(d)=digits(count)
OD
RETURN
PROC CheckScore(CHAR ARRAY code,guess Score POINTER res)
BYTE i,j
res.bulls=0
res.cows=0
IF guess(0)#DIGNUM THEN
res.err=1
RETURN
FI
res.err=0
FOR i=1 TO DIGNUM
DO
IF guess(i)=code(i) THEN
res.bulls==+1
ELSE
FOR j=1 TO DIGNUM
DO
IF j#i AND guess(j)=code(i) THEN
res.cows==+1
EXIT
FI
OD
FI
OD
RETURN
PROC Main()
CHAR ARRAY code(DIGNUM+1),guess(255)
Score res
Generate(code)
PrintE("Bull and cows game.") PutE()
Print("I choose a 4-digit number from digits 1 to 9 without repetition. ")
PrintE("Your goal is to guess it.") PutE()
PrintE("Enter your guess:")
DO
InputS(guess)
CheckScore(code,guess,res)
Put(28) ;cursor up
PrintF("%S -> ",guess)
IF res.err THEN
Print("Wrong input")
ELSE
PrintF("Bulls=%B Cows=%B",res.bulls,res.cows)
IF res.bulls=DIGNUM THEN
PutE() PutE()
PrintE("You win!")
EXIT
FI
FI
PrintE(", try again:")
OD
RETURN
- Output:
Screenshot from Atari 8-bit computer
Bull and cows game. I choose a 4-digit number from digits 1 to 9 without repetition. Your goal is to guess it. Enter your guess: 12345 -> Wrong input, try again: 1234 -> Bulls=0 Cows=2, try again: 1243 -> Bulls=2 Cows=0, try again: 5643 -> Bulls=2 Cows=0, try again: 7843 -> Bulls=3 Cows=0, try again: 7943 -> Bulls=2 Cows=1, try again: 9843 -> Bulls=4 Cows=0 You win!
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;
ALGOL 68
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))
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]:
APL
Call the moo
function with one dummy argument to play a game of
Bulls and Cows in the APL session.
input ← {⍞←'Guess: ' ⋄ 7↓⍞}
output ← {⎕←(↑'Bulls: ' 'Cows: '),⍕⍪⍵ ⋄ ⍵}
isdigits← ∧/⎕D∊⍨⊢
valid ← isdigits∧4=≢
guess ← ⍎¨input⍣(valid⊣)
bulls ← +/=
cows ← +/∊∧≠
game ← (output ⊣(bulls,cows) guess)⍣(4 0≡⊣)
random ← 1+4?9⍨
moo ← 'You win!'⊣(random game⊢)
To show off APL, this is written entirely in tacit style (except for the I/O). There is no explicit flow control or recursion,
and there are no variables. The code is split into functions only to aid the reader, none is ever
referred to twice. The following definition of moo
is exactly equivalent to the above:
moo←'You win!'⊣((1+4?9⍨)(({⎕←(↑'Bulls: ' 'Cows: '),⍕⍪⍵⋄⍵}⊣((+/=),(+/∊∧≠))(⍎¨{⍞←'Guess: '⋄7↓⍞}⍣(((∧/⎕D∊⍨⊢)∧4=≢)⊣)))⍣(4 0≡⊣))⊢)
AppleScript
GUI implementation; the prompt for a guess includes a list of all past guesses and their scores.
on pickNumber()
set theNumber to ""
repeat 4 times
set theDigit to (random number from 1 to 9) as string
repeat while (offset of theDigit in theNumber) > 0
set theDigit to (random number from 1 to 9) as string
end repeat
set theNumber to theNumber & theDigit
end repeat
end pickNumber
to bulls of theGuess given key:theKey
set bullCount to 0
repeat with theIndex from 1 to 4
if text theIndex of theGuess = text theIndex of theKey then
set bullCount to bullCount + 1
end if
end repeat
return bullCount
end bulls
to cows of theGuess given key:theKey, bulls:bullCount
set cowCount to -bullCount
repeat with theIndex from 1 to 4
if (offset of (text theIndex of theKey) in theGuess) > 0 then
set cowCount to cowCount + 1
end if
end repeat
return cowCount
end cows
to score of theGuess given key:theKey
set bullCount to bulls of theGuess given key:theKey
set cowCount to cows of theGuess given key:theKey, bulls:bullCount
return {bulls:bullCount, cows:cowCount}
end score
on run
set theNumber to pickNumber()
set pastGuesses to {}
repeat
set theMessage to ""
repeat with aGuess in pastGuesses
set {theGuess, theResult} to aGuess
set theMessage to theMessage & theGuess & ":" & bulls of theResult & "B, " & cows of theResult & "C" & linefeed
end repeat
set theMessage to theMessage & linefeed & "Enter guess:"
set theGuess to text returned of (display dialog theMessage with title "Bulls and Cows" default answer "")
set theScore to score of theGuess given key:theNumber
if bulls of theScore is 4 then
display dialog "Correct! Found the secret in " & ((length of pastGuesses) + 1) & " guesses!"
exit repeat
else
set end of pastGuesses to {theGuess, theScore}
end if
end repeat
end run
Arturo
rand: first.n: 4 unique map 1..10 => [sample 0..9]
bulls: 0
while [bulls <> 4][
bulls: new 0
cows: new 0
got: strip input "make a guess: "
if? or? not? numeric? got
4 <> size got -> print "Malformed answer. Try again!"
else [
loop.with:'i split got 'digit [
if? (to :integer digit) = rand\[i] -> inc 'bulls
else [
if contains? rand to :integer digit -> inc 'cows
]
]
print ["Bulls:" bulls "Cows:" cows "\n"]
]
]
print color #green "** Well done! You made the right guess!!"
AutoHotkey
length:=4, Code:="" ; settings
While StrLen(Code) < length {
Random, num, 1, 9
If !InStr(Code, num)
Code .= num
}
Gui, Add, Text, w83 vInfo, I'm thinking of a %length%-digit number with no duplicate digits.
Gui, Add, Edit, wp vGuess, Enter a guess...
Gui, Add, Button, wp Default vDefault, Submit
Gui, Add, Edit, ym w130 r8 vHistory ReadOnly
Gui, Show
Return
ButtonSubmit:
If Default = Restart
Reload
Gui, Submit, NoHide
If (StrLen(Guess) != length)
GuiControl, , Info, Enter a %length%-digit number.
Else If Guess is not digit
GuiControl, , Info, Enter a %length%-digit number.
Else
{
GuiControl, , Info
GuiControl, , Guess
If (Guess = Code)
{
GuiControl, , Info, Correct!
GuiControl, , Default, Restart
Default = Restart
}
response := Response(Guess, Code)
Bulls := SubStr(response, 1, InStr(response,",")-1)
Cows := SubStr(response, InStr(response,",")+1)
GuiControl, , History, % History . Guess ": " Bulls " Bulls " Cows " Cows`n"
}
Return
GuiEscape:
GuiClose:
ExitApp
Response(Guess,Code) {
Bulls := 0, Cows := 0
Loop, % StrLen(Code)
If (SubStr(Guess, A_Index, 1) = SubStr(Code, A_Index, 1))
Bulls++
Else If (InStr(Code, SubStr(Guess, A_Index, 1)))
Cows++
Return Bulls "," Cows
}
AWK
# Usage: GAWK -f BULLS_AND_COWS.AWK
BEGIN {
srand()
secret = ""
for (i = 1; i <= 4; ) {
digit = int(9 * rand()) + 1
if (index(secret, digit) == 0) {
secret = secret digit
i++
}
}
print "Welcome to 'Bulls and Cows'!"
print "I thought of a 4-digit number."
print "Please enter your guess."
}
iswellformed($0) {
if (calcscore($0, secret)) {
exit
}
}
function iswellformed(number, i, digit) {
if (number !~ /[1-9][1-9][1-9][1-9]/) {
print "Your guess should contain 4 digits, each from 1 to 9. Try again!"
return 0
}
for (i = 1; i <= 3; i++) {
digit = substr(number, 1, 1)
number = substr(number, 2)
if (index(number, digit) != 0) {
print "Your guess contains a digit twice. Try again!"
return 0
}
}
return 1
}
function calcscore(guess, secret, bulls, cows, i, idx) {
# Bulls = correct digits at the right position
# Cows = correct digits at the wrong position
for (i = 1; i <= 4; i++) {
idx = index(secret, substr(guess, i, 1))
if (idx == i) {
bulls++
} else if (idx > 0) {
cows++
}
}
printf("Your score for this guess: Bulls = %d, Cows = %d.", bulls, cows)
if (bulls < 4) {
printf(" Try again!\n")
} else {
printf("\nCongratulations, you win!\n")
}
return bulls == 4
}
- Output:
Welcome to 'Bulls and Cows'! I thought of a 4-digit number. Please enter your guess. 1234 Your score for this guess: Bulls = 0, Cows = 1. Try again! 5678 Your score for this guess: Bulls = 1, Cows = 1. Try again! 9651 Your score for this guess: Bulls = 1, Cows = 1. Try again! 5729 Your score for this guess: Bulls = 0, Cows = 3. Try again! 2695 Your score for this guess: Bulls = 2, Cows = 1. Try again! 2697 Your score for this guess: Bulls = 2, Cows = 2. Try again! 7692 Your score for this guess: Bulls = 4, Cows = 0. Congratulations, you win!
BASIC
DEFINT A-Z
DIM secret AS STRING
DIM guess AS STRING
DIM c AS STRING
DIM bulls, cows, guesses, i
RANDOMIZE TIMER
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
guess = LTRIM$(RTRIM$(guess))
IF LEN(guess) = 0 THEN EXIT DO
IF LEN(guess) <> 4 OR VAL(guess) = 0 THEN
PRINT "** You should enter 4 numeric digits!"
GOTO looper
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
looper:
LOOP
Applesoft BASIC
100 D$ = "123456789"
110 FOR I = 1 TO 4
120 P = INT(RND(1) * LEN(D$)) + 1
130 N$ = N$ + MID$(D$, P, 1)
140 D$ = MID$(D$, 1, P - 1) + MID$(D$, P + 1, 8)
150 NEXT
160 PRINT "A RANDOM NUMBER HAS BEEN CREATED.
170 PRINT "THE NUMBER HAS FOUR DIGITS FROM 1 TO 9, WITHOUT DUPLICATION."
200 FOR Q = 0 TO 1 STEP 0
210 INPUT "GUESS THE NUMBER: "; G%
220 G$ = STR$(G%)
230 M = LEN(G$) <> 4 OR G% = 0
240 IF NOT M THEN FOR I = 2 TO 4 : M = MID$(G$, I, 1) = "0" : IF NOT M THEN NEXT I
250 IF NOT M THEN FOR I = 1 TO 3 : FOR J = I + 1 TO 4 : M = MID$(G$, I, 1) = MID$(G$, J, 1) : IF NOT M THEN NEXT J, I
260 IF M THEN PRINT "THE GUESS IS MALFORMED." : NEXT Q
270 B = 0
280 C = 0
300 FOR I = 1 TO 4
310 C$ = MID$(N$, I, 1)
320 BULL = MID$(G$, I, 1) = C$
330 COW = 0
340 IF NOT BULL THEN FOR J = 1 TO 4 : COW = MID$(G$, J, 1) = C$ : IF NOT COW THEN NEXT J
350 B = B + BULL
360 C = C + COW
370 NEXT I
380 PRINT B " BULLS, " C " COWS"
390 Q = G$ = N$
400 NEXT Q
Commodore BASIC
Based on the AppleSoft BASIC version. Modifications as follows:
- Accommodate 80 character BASIC line length (for line 250 especially), created subroutines.
- Booleans in Commodore BASIC evaluate to -1 for TRUE, therefore ABS function added to give desired results.
- Leading space in printed numbers (which is placeholder for negative sign) is included in string conversion in Commodore BASIC, therefore RIGHT$ function added on 220 to trim leading whitespace upon conversion.
- Other formatting (clear screen, etc.) unique to Commodore BASIC.
100 D$="123456789"
110 FOR I=1 TO 4
120 P=INT(RND(1)*LEN(D$))+1
130 N$=N$+MID$(D$,P,1)
140 D$=MID$(D$,1,P - 1)+MID$(D$,P+1,8)
150 NEXT
160 PRINT CHR$(147);"A RANDOM NUMBER HAS BEEN CREATED."
170 PRINT "THE NUMBER HAS FOUR DIGITS FROM 1 TO 9, WITHOUT DUPLICATION."
200 FOR Q=0 TO 1 STEP 0
210 INPUT "GUESS THE NUMBER: "; G%
219 REM CONVERT TO STRING AND TRIM LEADING SPACE
220 G$=RIGHT$(STR$(G%),4)
230 M=LEN(G$)<>4 OR G%=0
240 IF NOT M THEN GOSUB 600
250 IF NOT M THEN GOSUB 700
260 IF M THEN PRINT "THE GUESS IS MALFORMED.":NEXT Q
270 B=0
280 C=0
300 FOR I=1 TO 4
310 C$=MID$(N$,I,1)
320 BULL=MID$(G$,I,1)=C$
330 COW=0
340 IF NOT BULL THEN FOR J=1 TO 4:COW=MID$(G$,J,1)=C$:IF NOT COW THEN NEXT J
350 B=B+ABS(BULL)
360 C=C+ABS(COW)
370 NEXT I
380 PRINT "BULLS:";B:PRINT "COWS:";C
390 Q=ABS(G$=N$)
400 NEXT Q
500 PRINT "GOOD JOB!":END
600 FOR I=2 TO 4:M=MID$(G$,I,1)="0"
610 IF NOT M THEN NEXT I
620 RETURN
700 FOR I=1 TO 3
710 FOR J=I+1 TO 4
720 M=MID$(G$,I,1)=MID$(G$,J,1)
730 IF NOT M THEN NEXT J,I
740 RETURN
IS-BASIC
100 PROGRAM "Bulls.bas"
110 RANDOMIZE
120 STRING C$*4
130 LET GUESS=0
140 DO
150 LET C$=STR$(RND(8701)+1199)
160 LOOP UNTIL CHECK$(C$)=C$
170 CLEAR SCREEN:PRINT "Welcome to 'Bulls and Cows!'"
180 DO
190 DO
200 PRINT :INPUT PROMPT "Guess a 4-digit number with no duplicate digits: ":G$
210 IF CHECK$(G$)="" THEN PRINT "You should enter 4-digit number with no duplicate digits."
220 LOOP UNTIL CHECK$(G$)=G$ AND G$<>""
230 LET GUESS=GUESS+1:LET BULLS,COWS=0
240 FOR I=1 TO 4
250 IF C$(I)=G$(I) THEN
260 LET BULLS=BULLS+1
270 ELSE IF POS(C$,G$(I))<>0 THEN
280 LET COWS=COWS+1
290 END IF
300 NEXT
310 PRINT BULLS;"bulls,";COWS;"cows"
320 LOOP UNTIL C$=G$
330 PRINT "You won after";GUESS;"guesses!"
340 DEF CHECK$(S$)
350 LET CHECK$=""
360 IF LEN(STR$(VAL(S$)))=4 AND POS(S$,"0")=0 THEN LET CHECK$=S$
370 FOR I=1 TO 4
380 IF POS(S$(:I-1),S$(I)) OR POS(S$(I+1:),S$(I)) THEN LET CHECK$=""
390 NEXT
400 END DEF
ZX Spectrum Basic
10 DIM n(10): LET c$=""
20 FOR i=1 TO 4
30 LET d=INT (RND*9+1)
40 IF n(d)=1 THEN GO TO 30
50 LET n(d)=1
60 LET c$=c$+STR$ d
70 NEXT i
80 LET guesses=0
90 INPUT "Guess a 4-digit number (1 to 9) with no duplicate digits: ";guess
100 IF guess=0 THEN STOP
110 IF guess>9999 OR guess<1000 THEN PRINT "Only 4 numeric digits, please": GO TO 90
120 LET bulls=0: LET cows=0: LET guesses=guesses+1: LET g$=STR$ guess
130 FOR i=1 TO 4
140 IF g$(i)=c$(i) THEN LET bulls=bulls+1: GO TO 160
150 IF n(VAL g$(i))=1 THEN LET cows=cows+1
160 NEXT i
170 PRINT bulls;" bulls, ";cows;" cows"
180 IF c$=g$ THEN PRINT "You won after ";guesses;" guesses!": GO TO 10
190 GO TO 90
Batch File
:: Bulls and Cows Task from Rosetta Code
:: Batch File Implementation
@echo off
setlocal enabledelayedexpansion
:: initialization
:begin
set "list_chars=123456789"
set "list_length=9"
set "code="
set "code_length=4" %== this should be less than 10 ==%
set "tries=0" %== number of tries ==%
:: generate the code to be guessed by player
set "chars_left=%list_chars%"
for /l %%c in (1, 1, %code_length%) do (
set /a "rnd=!random! %% (%list_length% + 1 - %%c)"
for %%? in (!rnd!) do set "pick_char=!chars_left:~%%?,1!"
set "code=!code!!pick_char!"
for %%? in (!pick_char!) do set "chars_left=!chars_left:%%?=!"
)
:: get the min and max allowable guess for input validation
set "min=!list_chars:~0,%code_length%!"
set "max="
for /l %%c in (1, 1, %code_length%) do set "max=!max!!list_chars:~-%%c,1!"
:: display game
:display
cls
echo(
echo(Bulls and Cows Game
echo(Batch File Implementation
echo(
echo(Gameplay:
echo(
echo(I have generated a %code_length%-digit code from digits 1-9 without duplication.
echo(Your objective is to guess it. If your guess is equal to my code,
echo(then you WIN. If not, I will score your guess:
echo(
echo(** A score of one BULL is accumulated for each digit in your guess
echo(that equals the corresponding digit in my code.
echo(
echo(** A score of one COW is accumulated for each digit in your guess
echo(that also appears in my code, but in the WRONG position.
echo(
echo(Now, start guessing^^!
:: input guess
:guess
echo(
set "guess=" %== clear input ==%
set /p "guess=Your Guess: "
:: validate input
if "!guess!" gtr "%max%" goto invalid
if "!guess!" lss "%min%" goto invalid
set /a "last_idx=%code_length% - 1"
for /l %%i in (0, 1, %last_idx%) do (
set /a "next_idx=%%i + 1"
for /l %%j in (!next_idx!, 1, %last_idx%) do (
if "!guess:~%%i,1!" equ "!guess:~%%j,1!" goto invalid
)
)
goto score
:: display that input is invalid
:invalid
echo(Please input a valid guess.
goto guess
:: scoring section
:score
set /a "tries+=1"
if "%guess%" equ "%code%" goto win
set "cow=0"
set "bull=0"
for /l %%i in (0, 1, %last_idx%) do (
for /l %%j in (0, 1, %last_idx%) do (
if "!guess:~%%i,1!" equ "!code:~%%j,1!" (
if "%%i" equ "%%j" (
set /a "bull+=1"
) else (
set /a "cow+=1"
)
)
)
)
:: display score and go back to user input
echo(BULLS = %bull%; COWS = %cow%.
goto guess
:: player wins!
:win
echo(
echo(After %tries% tries, YOU CRACKED IT^^! My code is %code%.
echo(
set /p "opt=Play again? "
if /i "!opt!" equ "y" goto begin
exit /b 0
- Output:
Bulls and Cows Game Batch File Implementation Gameplay: I have generated a 4-digit code from digits 1-9 without duplication. Your objective is to guess it. If your guess is equal to my code, then you WIN. If not, I will score your guess: ** A score of one BULL is accumulated for each digit in your guess that equals the corresponding digit in my code. ** A score of one COW is accumulated for each digit in your guess that also appears in my code, but in the WRONG position. Now, start guessing! Your Guess: 0123 Please input a valid guess. Your Guess: 1234 BULLS = 0; COWS = 3. Your Guess: 4123 BULLS = 2; COWS = 1. ... Your Guess: 4391 BULLS = 2; COWS = 0. Your Guess: 4521 BULLS = 3; COWS = 0. Your Guess: 4621 BULLS = 3; COWS = 0. Your Guess: 4821 After 10 tries, YOU CRACKED IT! My code is 4821. Play again?
BBC BASIC
secret$ = ""
REPEAT
c$ = CHR$(&30 + RND(9))
IF INSTR(secret$, c$) = 0 secret$ += c$
UNTIL LEN(secret$) = 4
PRINT "Guess a four-digit number with no digit used twice."'
guesses% = 0
REPEAT
REPEAT
INPUT "Enter your guess: " guess$
IF LEN(guess$) <> 4 PRINT "Must be a four-digit number"
UNTIL LEN(guess$) = 4
guesses% += 1
IF guess$ = secret$ PRINT "You won after "; guesses% " guesses!" : END
bulls% = 0
cows% = 0
FOR i% = 1 TO 4
c$ = MID$(secret$, i%, 1)
IF MID$(guess$, i%, 1) = c$ THEN
bulls% += 1
ELSE IF INSTR(guess$, c$) THEN
cows% += 1
ENDIF
ENDIF
NEXT i%
PRINT "You got " ;bulls% " bull(s) and " ;cows% " cow(s)."
UNTIL FALSE
BCPL
get "libhdr"
static $( randstate = ? $)
let randdigit() = valof
$( let x = ?
$( randstate := random(randstate)
x := (randstate >> 7) & 15
$) repeatuntil 0 < x <= 9
resultis x
$)
let gensecret(s) be
for i=0 to 3
s!i := randdigit() repeatuntil valof
$( for j=0 to i-1 if s!i = s!j then resultis false
resultis true
$)
let bulls(secret, guess) = valof
$( let x = 0
for i=0 to 3 if secret!i = guess!i then x := x + 1
resultis x
$)
let cows(secret, guess) = valof
$( let x = 0
for i=0 to 3
for j=0 to 3
unless i=j
if secret!i = guess!j then x := x + 1
resultis x
$)
let readguess(guess) be
$( let g, v = ?, true
writes("Enter a guess, or 0 to quit: ")
g := readn()
if g=0 then finish
for i=3 to 0 by -1
$( guess!i := g rem 10
g := g / 10
$)
for i=0 to 2 for j = i+1 to 3
v := v & guess!i ~= 0 & guess!j ~= 0 & guess!i ~= guess!j
if v then return
writes("Invalid guess.*N")
$) repeat
let play(secret) be
$( let tries, b, c = 0, ?, ?
let guess = vec 3
$( readguess(guess)
b := bulls(secret, guess)
c := cows(secret, guess)
writef("Bulls: %N, cows: %N*N", b, c);
tries := tries + 1
$) repeatuntil b = 4
writef("You win in %N tries.*N", tries)
$)
let start() be
$( let secret = vec 3
writes("Bulls and cows*N----- --- ----*N")
writes("Please enter a random seed: ")
randstate := readn()
wrch('*N')
gensecret(secret)
play(secret)
$)
- Output:
Bulls and cows ----- --- ---- Please enter a random seed: 20394 Enter a guess, or 0 to quit: 1234 Bulls: 0, cows: 3 Enter a guess, or 0 to quit: 4321 Bulls: 1, cows: 2 Enter a guess, or 0 to quit: 1423 Bulls: 2, cows: 1 Enter a guess, or 0 to quit: 1243 Bulls: 1, cows: 2 Enter a guess, or 0 to quit: 4123 Bulls: 3, cows: 0 Enter a guess, or 0 to quit: 4523 Bulls: 2, cows: 0 Enter a guess, or 0 to quit: 5123 Bulls: 3, cows: 0 Enter a guess, or 0 to quit: 6123 Bulls: 3, cows: 0 Enter a guess, or 0 to quit: 7123 Bulls: 4, cows: 0 You win in 9 tries.
Brat
secret_length = 4
secret = [1 2 3 4 5 6 7 8 9].shuffle.pop secret_length
score = { guess |
cows = 0
bulls = 0
guess.each_with_index { digit, index |
true? digit == secret[index]
{ bulls = bulls + 1 }
{ true? secret.include?(digit)
{ cows = cows + 1 }
}
}
[cows: cows, bulls: bulls]
}
won = false
guesses = 1
p "I have chosen a number with four unique digits from 1 through 9. Can you guess it?"
while { not won }
{
print "Guess #{guesses}: "
guess = g.strip.dice.map { d | d.to_i }
when { guess == secret } { p "You won in #{guesses} guesses!"; won = true }
{ guess.include?(0) || guess.include?(null) } { p "Your guess should only include digits 1 through 9." }
{ guess.length != secret.length } { p "Your guess was not the correct length. The number has exactly #{secret.length} digits." }
{ guess.unique.length != secret.length } { p "Each digit should only appear once in your guess." }
{ true } {
result = score guess
p "Score: #{result[:bulls]} bulls, #{result[:cows]} cows."
guesses = guesses + 1
}
}
C
#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;
}
C#
using System;
namespace BullsnCows
{
class Program
{
static void Main(string[] args)
{
int[] nums = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
KnuthShuffle<int>(ref nums);
int[] chosenNum = new int[4];
Array.Copy(nums, chosenNum, 4);
Console.WriteLine("Your Guess ?");
while (!game(Console.ReadLine(), chosenNum))
{
Console.WriteLine("Your next Guess ?");
}
Console.ReadKey();
}
public static void KnuthShuffle<T>(ref T[] array)
{
System.Random random = new System.Random();
for (int i = 0; i < array.Length; i++)
{
int j = random.Next(array.Length);
T temp = array[i]; array[i] = array[j]; array[j] = temp;
}
}
public static bool game(string guess, int[] num)
{
char[] guessed = guess.ToCharArray();
int bullsCount = 0, cowsCount = 0;
if (guessed.Length != 4)
{
Console.WriteLine("Not a valid guess.");
return false;
}
for (int i = 0; i < 4; i++)
{
int curguess = (int) char.GetNumericValue(guessed[i]);
if (curguess < 1 || curguess > 9)
{
Console.WriteLine("Digit must be ge greater 0 and lower 10.");
return false;
}
if (curguess == num[i])
{
bullsCount++;
}
else
{
for (int j = 0; j < 4; j++)
{
if (curguess == num[j])
cowsCount++;
}
}
}
if (bullsCount == 4)
{
Console.WriteLine("Congratulations! You have won!");
return true;
}
else
{
Console.WriteLine("Your Score is {0} bulls and {1} cows", bullsCount, cowsCount);
return false;
}
}
}
}
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";
unsigned 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(guess))
{
std::cout << guess << " is not a valid guess!";
continue;
}
unsigned int bulls = 0;
unsigned 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? ";
}
}
Ceylon
import ceylon.random {
DefaultRandom
}
shared void run() {
value random = DefaultRandom();
function generateDigits() =>
random.elements(1..9).distinct.take(4).sequence();
function validate(String guess) {
variable value ok = true;
if (!guess.every((Character element) => element.digit)) {
print("numbers only, please");
ok = false;
}
if ('0' in guess) {
print("only 1 to 9, please");
ok = false;
}
if (guess.distinct.shorterThan(guess.size)) {
print("no duplicates, please");
ok = false;
}
if (guess.size != 4) {
print("4 digits please");
ok = false;
}
return ok;
}
function score({Integer*} target, {Integer*} guess) {
variable value bulls = 0;
variable value cows = 0;
for ([a, b] in zipPairs(target, guess)) {
if (a == b) {
bulls++;
} else if (target.contains(b)) {
cows++;
}
}
return [bulls, cows];
}
while (true) {
value digits = generateDigits();
print("I have chosen my four digits, please guess what they are.
Use only the digits 1 to 9 with no duplicates and enter them with no spaces. eg 1234
Enter q or Q to quit.");
while (true) {
if (exists line = process.readLine()) {
if (line.uppercased == "Q") {
return;
}
if (validate(line)) {
value guessDigits = line.map((Character element) => Integer.parse(element.string)).narrow<Integer>();
value [bulls, cows] = score(digits, guessDigits);
if (bulls == 4) {
print("You win!");
break;
}
else {
print("Bulls: ``bulls``, Cows: ``cows``");
}
}
}
}
}
}
Clojure
(ns bulls-and-cows)
(defn bulls [guess solution]
(count (filter true? (map = guess solution))))
(defn cows [guess solution]
(-
(count (filter (set solution) guess))
(bulls guess solution)))
(defn valid-input?
"checks whether the string is a 4 digit number with unique digits"
[user-input]
(if (re-seq #"^(?!.*(\d).*\1)\d{4}$" user-input)
true
false))
(defn enter-guess []
"Let the user enter a guess. Verify the input. Repeat until valid.
returns a list of digits enters by the user (# # # #)"
(println "Enter your guess: ")
(let [guess (read-line)]
(if (valid-input? guess)
(map #(Character/digit % 10) guess)
(recur))))
(defn bulls-and-cows []
"generate a random 4 digit number from the list of (1 ... 9): no repeating digits
player tries to guess the number with bull and cows rules gameplay"
(let [solution ( take 4 (shuffle (range 1 10)))]
(println "lets play some bulls and cows!")
(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)
CLU
% This program needs to be merged with PCLU's "misc" library
% to use the random number generator.
%
% pclu -merge $CLUHOME/lib/misc.lib -compile bulls_cows.clu
% Seed the random number generator with the current time
init_rng = proc ()
d: date := now()
seed: int := ((d.hour*60) + d.minute)*60 + d.second
random$seed(seed)
end init_rng
% Generate a secret
make_secret = proc () returns (sequence[int])
secret: array[int] := array[int]$[0,0,0,0]
for i: int in int$from_to(1,4) do
digit: int
valid: bool := false
while ~valid do
digit := 1+random$next(9)
valid := true
for j: int in int$from_to(1, i-1) do
if secret[i] = digit then
valid := false
break
end
end
end
secret[i] := digit
end
return(sequence[int]$a2s(secret))
end make_secret
% Count the bulls
bulls = proc (secret, input: sequence[int]) returns (int)
n_bulls: int := 0
for i: int in int$from_to(1,4) do
if secret[i] = input[i] then n_bulls := n_bulls + 1 end
end
return(n_bulls)
end bulls
% Count the cows
cows = proc (secret, input: sequence[int]) returns (int)
n_cows: int := 0
for i: int in int$from_to(1,4) do
for j: int in int$from_to(1,4) do
if i ~= j cand secret[i] = input[j] then
n_cows := n_cows + 1
end
end
end
return(n_cows)
end cows
% Read a guess
player_guess = proc () returns (sequence[int])
pi: stream := stream$primary_input()
po: stream := stream$primary_output()
while true do % we will keep reading until the guess is valid
stream$puts(po, "Guess? ")
guess: string := stream$getl(pi)
% check length
if string$size(guess) ~= 4 then
stream$putl(po, "Invalid guess: need four digits.")
continue
end
% get and check digits
valid: bool := true
digits: sequence[int] := sequence[int]$[]
for c: char in string$chars(guess) do
i: int := char$c2i(c) - 48
if ~(i>=1 & i<=9) then
valid := false
break
end
digits := sequence[int]$addh(digits,i)
end
if ~valid then
stream$putl(po, "Invalid guess: each position needs to be a digit 1-9.")
continue
end
% check that there are no duplicates
valid := true
for i: int in int$from_to(1,4) do
for j: int in int$from_to(i+1,4) do
if digits[i] = digits[j] then
valid := false
break
end
end
end
if ~valid then
stream$putl(po, "Invalid guess: there must be no duplicate digits.")
continue
end
return(digits)
end
end player_guess
% Play a game
play_game = proc (secret: sequence[int])
po: stream := stream$primary_output()
n_guesses: int := 0
while true do
n_guesses := n_guesses + 1
guess: sequence[int] := player_guess()
n_bulls: int := bulls(secret, guess)
n_cows: int := cows(secret, guess)
stream$putl(po, "Bulls: " || int$unparse(n_bulls)
|| ", cows: " || int$unparse(n_cows))
if n_bulls = 4 then
stream$putl(po, "Congratulations! You won in "
|| int$unparse(n_guesses) || " tries.")
break
end
end
end play_game
start_up = proc ()
po: stream := stream$primary_output()
init_rng()
stream$putl(po, "Bulls and cows\n----- --- ----\n")
play_game(make_secret())
end start_up
- Output:
Bulls and cows ----- --- ---- Guess? 1234 Bulls: 0, cows: 1 Guess? 5678 Bulls: 0, cows: 2 Guess? 4579 Bulls: 1, cows: 2 Guess? 3579 Bulls: 2, cows: 2 Guess? 3759 Bulls: 4, cows: 0 Congratulations! You won in 5 tries.
Coco
To handle I/O, we use functions named say
(which simply outputs a string) and prompt
(which takes a prompt string to display to the user and returns a line of input, without a trailing newline). These require platform-specific implementations. Here's how they can be implemented for the SpiderMonkey shell:
say = print
prompt = (str) ->
putstr str
readline! ? quit!
We can now solve the task using say
and prompt
:
const SIZE = 4
secret = _.sample ['1' to '9'], SIZE
for ever
var guess
for ever
guess := _.uniq prompt 'Enter a guess: '
if guess.length === SIZE and not _.difference guess, ['1' to '9'] .length
break
say 'Malformed guess; try again.'
bulls = cows = 0
for i til SIZE
if guess[i] === secret[i]
++bulls
else if _.contains secret, guess[i]
++cows
if bulls === SIZE
break
say "#bulls bull#{[if bulls !== 1 then 's']}, #cows cow#{[if cows !== 1 then 's']}."
say 'A winner is you!'
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)))))))
Crystal
size = 4
secret = ('1'..'9').to_a.sample(size)
guess = [] of Char
i = 0
loop do
i += 1
loop do
print "Guess #{i}: "
guess = gets.not_nil!.chomp.chars
exit if guess.empty?
break if guess.size == size &&
guess.all? { |x| ('1'..'9').includes? x } &&
guess.uniq.size == size
puts "Problem, try again. You need to enter #{size} unique digits from 1 to 9"
end
if guess == secret
puts "Congratulations you guessed correctly in #{i} attempts"
break
end
bulls = cows = 0
size.times do |j|
if guess[j] == secret[j]
bulls += 1
elsif secret.includes? guess[j]
cows += 1
end
end
puts "Bulls: #{bulls}; Cows: #{cows}"
end
D
void main() {
import std.stdio, std.random, std.string, std.algorithm,
std.range, std.ascii;
immutable hidden = "123456789"d.randomCover.take(4).array;
while (true) {
"Next guess: ".write;
const d = readln.strip.array.sort().release;
if (d.count == 4 && d.all!isDigit && d.uniq.count == 4) {
immutable bulls = d.zip(hidden).count!q{ a[0] == a[1] },
cows = d.count!(g => hidden.canFind(g)) - bulls;
if (bulls == 4)
return " You guessed it!".writeln;
writefln("bulls %d, cows %d", bulls, cows);
}
" Bad guess! (4 unique digits, 1-9)".writeln;
}
}
- Output:
Next guess: 6548 bulls 0, cows 3 Bad guess! (4 unique digits, 1-9) Next guess: 5284 bulls 2, cows 1 Bad guess! (4 unique digits, 1-9) Next guess: 4386 bulls 0, cows 2 Bad guess! (4 unique digits, 1-9) Next guess: - Bad guess! (4 unique digits, 1-9) Next guess: 5894 bulls 3, cows 0 Bad guess! (4 unique digits, 1-9) Next guess: 5874 bulls 3, cows 0 Bad guess! (4 unique digits, 1-9) Next guess: 5814 You guessed it!
Delphi
See #Pascal.
Draco
union {
ulong state;
struct {
byte x;
byte a;
byte b;
byte c;
} fields;
} rng;
proc rand() byte:
rng.fields.x := rng.fields.x + 1;
rng.fields.a := rng.fields.a >< rng.fields.c >< rng.fields.x;
rng.fields.b := rng.fields.b + rng.fields.a;
rng.fields.c := rng.fields.c + (rng.fields.b >> 1) >< rng.fields.a;
rng.fields.c
corp
proc rand_digit() byte:
byte digit;
while
digit := rand() & 15;
digit < 1 or digit >= 10
do od;
digit
corp
proc make_secret([4]byte secret) void:
int i, j;
bool ok;
for i from 0 upto 3 do
while
secret[i] := rand_digit();
ok := true;
for j from 0 upto i-1 do
ok := ok and secret[i] /= secret[j]
od;
not ok
do od
od
corp
proc bulls([4]byte secret, guess) byte:
byte i, count;
count := 0;
for i from 0 upto 3 do
if secret[i] = guess[i] then count := count + 1 fi
od;
count
corp
proc cows([4]byte secret, guess) byte:
byte i, j, count;
count := 0;
for i from 0 upto 3 do
for j from 0 upto 3 do
if i /= j and secret[i] = guess[j] then count := count + 1 fi
od
od;
count
corp
proc read_guess([4]byte guess) void:
word guessNo;
byte i;
while
write("Guess? ");
readln(guessNo);
if guessNo<1111 or guessNo>9999 then true
else
for i from 3 downto 0 do
guess[i] := guessNo % 10;
guessNo := guessNo / 10;
od;
guess[0]*guess[1]*guess[2]*guess[3] = 0
fi
do
writeln("A guess must be a four-digit number not containing zeroes.")
od
corp
proc play_game([4]byte secret) word:
[4]byte guess;
word tries;
tries := 1;
while
read_guess(guess);
writeln("Bulls: ", bulls(secret, guess), ", cows: ", cows(secret, guess));
bulls(secret, guess) /= 4
do
tries := tries + 1
od;
tries
corp
proc main() void:
[4]byte secret;
word tries;
write("Please enter a random seed: ");
readln(rng.state);
make_secret(secret);
tries := play_game(secret);
writeln();
writeln("You got it in ", tries, " tries.")
corp
- Output:
Please enter a random seed: 123456 Guess? 1234 Bulls: 2, cows: 1 Guess? 5678 Bulls: 0, cows: 0 Guess? 9234 Bulls: 1, cows: 2 Guess? 1934 Bulls: 3, cows: 0 Guess? 1294 Bulls: 2, cows: 2 Guess? 1924 Bulls: 4, cows: 0 You got it in 6 tries.
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()
}
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()}`) } }
Graphical user interface
(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)
}
EasyLang
dig[] = [ 1 2 3 4 5 6 7 8 9 ]
for i = 1 to 4
h = i - 1 + random (10 - i)
swap dig[i] dig[h]
.
# print dig[]
len g[] 4
attempts = 0
repeat
repeat
ok = 0
s$[] = strchars input
if len s$[] = 4
ok = 1
for i = 1 to 4
g[i] = number s$[i]
if g[i] = 0
ok = 0
.
.
.
until ok = 1
.
print g[]
attempts += 1
bulls = 0
cows = 0
for i = 1 to 4
if g[i] = dig[i]
bulls += 1
else
for j = 1 to 4
if dig[j] = g[i]
cows += 1
.
.
.
.
print "bulls:" & bulls & " cows:" & cows
until bulls = 4
.
print "Well done! " & attempts & " attempts needed."
Eiffel
class
BULLS_AND_COWS
create
execute
feature
execute
-- Initiate game.
do
io.put_string ("Let's play bulls and cows.%N")
create answer.make_empty
play
end
feature {NONE}
play
-- Plays bulls ans cows.
local
count, seed: INTEGER
guess: STRING
do
from
until
seed > 0
loop
io.put_string ("Enter a positive integer.%NYour play will be generated from it.%N")
io.read_integer
seed := io.last_integer
end
generate_answer (seed)
io.put_string ("Your game has been created.%N Try to guess the four digit number.%N")
create guess.make_empty
from
until
guess ~ answer
loop
io.put_string ("Guess: ")
io.read_line
guess := io.last_string
if guess.count = 4 and guess.is_natural and not guess.has ('0') then
io.put_string (score (guess) + "%N")
count := count + 1
else
io.put_string ("Your input does not have the correct format.")
end
end
io.put_string ("Congratulations! You won with " + count.out + " guesses.")
end
answer: STRING
generate_answer (s: INTEGER)
-- Answer with 4-digits between 1 and 9 stored in 'answer'.
require
positive_seed: s > 0
local
random: RANDOM
ran: INTEGER
do
create random.set_seed (s)
from
until
answer.count = 4
loop
ran := (random.double_item * 10).floor
if ran > 0 and not answer.has_substring (ran.out) then
answer.append (ran.out)
end
random.forth
end
ensure
answer_not_void: answer /= Void
correct_length: answer.count = 4
end
score (g: STRING): STRING
-- Score for the guess 'g' depending on 'answer'.
require
same_length: answer.count = g.count
local
k: INTEGER
a, ge: STRING
do
Result := ""
a := answer.twin
ge := g.twin
across
1 |..| a.count as c
loop
if a [c.item] ~ ge [c.item] then
Result := Result + "BULL "
a [c.item] := ' '
ge [c.item] := ' '
end
end
across
1 |..| a.count as c
loop
if a [c.item] /= ' ' then
k := ge.index_of (a [c.item], 1)
if k > 0 then
Result := Result + "COW "
ge [k] := ' '
end
end
end
end
end
- Output:
Let's play bulls and cows. Enter a positive integer. Your play will be generated from it. 2 Guess: 2497 BULL COW Guess: 2486 BULL COW COW Guess: 2485 BULL COW COW Guess: 2483 BULL BULL COW COW Guess: 2438 BULL COW COW COW Guess: 2843 BULL BULL BULL BULL Congratulations! You won with 6 guesses.
Elena
ELENA 6.x :
import system'routines;
import extensions;
class GameMaster
{
field _numbers;
field _attempt;
constructor()
{
// generate secret number
var randomNumbers := new int[]{1,2,3,4,5,6,7,8,9}.randomize(9);
_numbers := randomNumbers.Subarray(0, 4);
_attempt := new Integer(1);
}
ask()
{
var row := console.print("Your Guess #",_attempt," ?").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 == _numbers[i])
{
bulls += 1
}
else
{
if (_numbers.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 }
! {
_attempt.append(1);
console.printLine("Your Score is ",bulls," bulls and ",cows," cows");
^ true
}
}
}
public program()
{
var gameMaster := new GameMaster();
var process := $lazy gameMaster.proceed(gameMaster.ask());
process.doWhile();
console.readChar()
}
- Output:
Your Guess #1 ?2497 Your Score is 1 bulls and 1 cows Your Guess #2 ?2486 Your Score is 1 bulls and 2 cows Your Guess #3 ?2485 Your Score is 1 bulls and 2 cows Your Guess #4 ?2483 Your Score is 2 bulls and 2 cows Your Guess #5 ?2438 Your Score is 1 bulls and 3 cows Your Guess #6 ?2843 Congratulations! You have won!
Elixir
defmodule Bulls_and_cows do
def play(size \\ 4) do
secret = Enum.take_random(1..9, size) |> Enum.map(&to_string/1)
play(size, secret)
end
defp play(size, secret) do
guess = input(size)
if guess == secret do
IO.puts "You win!"
else
{bulls, cows} = count(guess, secret)
IO.puts " Bulls: #{bulls}; Cows: #{cows}"
play(size, secret)
end
end
defp input(size) do
guess = IO.gets("Enter your #{size}-digit guess: ") |> String.strip
cond do
guess == "" ->
IO.puts "Give up"
exit(:normal)
String.length(guess)==size and String.match?(guess, ~r/^[1-9]+$/) ->
String.codepoints(guess)
true -> input(size)
end
end
defp count(guess, secret) do
Enum.zip(guess, secret) |>
Enum.reduce({0,0}, fn {g,s},{bulls,cows} ->
cond do
g == s -> {bulls + 1, cows}
g in secret -> {bulls, cows + 1}
true -> {bulls, cows}
end
end)
end
end
Bulls_and_cows.play
- Output:
Enter your 4-digit guess: 1234 Bulls: 1; Cows: 1 Enter your 4-digit guess: 5678 Bulls: 0; Cows: 2 Enter your 4-digit guess: 2345 Bulls: 0; Cows: 1 Enter your 4-digit guess: 1456 Bulls: 1; Cows: 0 Enter your 4-digit guess: 1782 You win!
Erlang
Module:
-module(bulls_and_cows).
-export([generate_secret/0, score_guess/2, play/0]).
% generate the secret code
generate_secret() -> generate_secret([], 4, lists:seq(1,9)).
generate_secret(Secret, 0, _) -> Secret;
generate_secret(Secret, N, Digits) ->
Next = lists:nth(random:uniform(length(Digits)), Digits),
generate_secret(Secret ++ [Next], N - 1, Digits -- [Next]).
% evaluate a guess
score_guess(Secret, Guess)
when length(Secret) =/= length(Guess) -> throw(badguess);
score_guess(Secret, Guess) ->
Bulls = count_bulls(Secret,Guess),
Cows = count_cows(Secret, Guess, Bulls),
[Bulls, Cows].
% count bulls (exact matches)
count_bulls(Secret, Guess) ->
length(lists:filter(fun(I) -> lists:nth(I,Secret) == lists:nth(I,Guess) end,
lists:seq(1, length(Secret)))).
% count cows (digits present but out of place)
count_cows(Secret, Guess, Bulls) ->
length(lists:filter(fun(I) -> lists:member(I, Guess) end, Secret)) - Bulls.
% play a game
play() -> play_round(generate_secret()).
play_round(Secret) -> play_round(Secret, read_guess()).
play_round(Secret, Guess) ->
play_round(Secret, Guess, score_guess(Secret,Guess)).
play_round(_, _, [4,0]) ->
io:put_chars("Correct!\n");
play_round(Secret, _, Score) ->
io:put_chars("\tbulls:"), io:write(hd(Score)), io:put_chars(", cows:"),
io:write(hd(tl(Score))), io:put_chars("\n"), play_round(Secret).
read_guess() ->
lists:map(fun(D)->D-48 end,
lists:sublist(io:get_line("Enter your 4-digit guess: "), 4)).
Script:
#!/usr/bin/escript
% Play Bulls and Cows
main(_) -> random:seed(now()), bulls_and_cows:play().
Sample play:
Enter your 4-digit guess: 8376 bulls:1, cows:0 Enter your 4-digit guess: 8941 bulls:1, cows:1 Enter your 4-digit guess: 8529 bulls:1, cows:1 Enter your 4-digit guess: 4926 bulls:1, cows:1 Enter your 4-digit guess: 9321 Correct!
Euphoria
include std\text.e
include std\os.e
include std\sequence.e
include std\console.e
sequence bcData = {0,0} --bull,cow score for the player
sequence goalNum = { {0,0,0,0}, {0,0,0,0}, 0} --computer's secret number digits (element 1), marked as bull/cow
--indexes in element 2, integer value of it in element 3
sequence currentGuess = { {0,0,0,0}, {0,0,0,0}, 0} --player's guess, same format as goalNum
sequence removeChars = 0 & " 0\r\t\n" --characters to trim (remove) from user's input. \r, \t are single escaped characters,
--0 is ascii 0x0 and number zero is ascii 48, or 0x30. The rest are wysiwyg
integer tries = 0 --track number of tries to guess the number
sequence bcStrings ={"bull", "cow"} --stores singular and/or plural strings depending on score in bcData
goalNum[1] = rand( {9,9,9,9} ) --rand function works on objects. here it outputs into each sequence element.
goalNum[3] = goalNum[1][1] * 1000 + goalNum[1][2] * 100 + goalNum[1][3] * 10 + goalNum[1][4] --convert digits to an integer
--and store it
procedure getInputAndProcess(integer stage = 1) --object = 1 sets default value for the parameter if it isn't specified
goalNum[2][1..4] = 0 --{0,0,0,0} --set these to unscaned (0) since the scanning will start over.
currentGuess[1][1..4] = 0 --{0,0,0,0} --these too, or they will contain old marks
currentGuess[2][1..4] = 0
tries += 1 --equivalent to tries = tries + 1, but faster and shorter to write
bcData[1..2] = 0 -- {0,0}
if stage <= 1 then --if this process was run for the first time or with no parameters, then..
puts(1,"The program has thought of a four digit number using only digits 1 to 9.\nType your guess and press enter.\n")
end if
while 1 label "guesscheck" do --labels can be used to specify a jump point from exit or retry, and help readability
currentGuess[1] = trim(gets(0), removeChars) --get user input, trim unwanted characters from it, store it in currentGuess[1]
currentGuess[1] = mapping( currentGuess[1], {49,50,51,52,53,54,55,56,57}, {1,2,3,4,5,6,7,8,9} ) --convert ascii codes to
-- integer digits they represent
integer tempF = find('0',currentGuess[1])
if length(currentGuess[1]) != 4 or tempF != 0 then --if the input string is now more than 4 characters/integers,
--the input won't be used.
puts(1,"You probably typed too many digits or a 0. Try typing a new 4 digit number with only numbers 1 through 9.\n")
retry "guesscheck"
else
exit "guesscheck"
end if
end while
--convert separate digits to the one integer they represent and store it, like with goalNum[3]
currentGuess[3] = currentGuess[1][1] * 1000 + currentGuess[1][2] * 100 + currentGuess[1][3] * 10 + currentGuess[1][4]
--convert digits to the integer they represent, to print to a string later
--check for bulls
for i = 1 to 4 do
if goalNum[1][i] = currentGuess[1][i] then
goalNum[2][i] = 1
currentGuess[2][i] = 1
bcData[1] += 1
end if
end for
--check for cows, but not slots marked as bulls or cows already.
for i = 1 to 4 label "iGuessElem"do --loop through each guessed digit
for j = 1 to 4 label "jGoalElem" do --but first go through each goal digit, comparing the first guessed digit,
--and then the other guessed digits 2 through 4
if currentGuess[2][i] = 1 then --if the guessed digit we're comparing right now has been marked as bull or cow already
continue "iGuessElem" --skip to the next guess digit without comparing this guess digit to the other goal digits
end if
if goalNum[2][j] = 1 then --if the goal digit we're comparing to right now has been marked as a bull or cow already
continue "jGoalElem" --skip to the next goal digit
end if
if currentGuess[1][i] = goalNum[1][j] then --if the guessed digit is the same as the goal one,
--it won't be a bull, so it's a cow
bcData[2] += 1 --score one more cow
goalNum[2][j] = 1 --mark this digit as a found cow in the subsequence that stores 0's or 1's as flags
continue "iGuessElem" --skip to the next guess digit, so that this digit won't try to check for
--matches(cow) with other goal digits
end if
end for --this guess digit was compared to one goal digit , try comparing this guess digit with the next goal digit
end for --this guess digit was compared with all goal digits, compare the next guess digit to all the goal digits
if bcData[1] = 1 then --uses singular noun when there is score of 1, else plural
bcStrings[1] = "bull"
else
bcStrings[1] = "bulls"
end if
if bcData[2] = 1 then --the same kind of thing as above block
bcStrings[2] = "cow"
else
bcStrings[2] = "cows"
end if
if bcData[1] < 4 then --if less than 4 bulls were found, the player hasn't won, else they have...
printf(1, "Guess #%d : You guessed %d . You found %d %s, %d %s. Type new guess.\n", {tries, currentGuess[3], bcData[1], bcStrings[1], bcData[2], bcStrings[2]} )
getInputAndProcess(2)
else --else they have won and the procedure ends
printf(1, "The number was %d. You guessed %d in %d tries.\n", {goalNum[3], currentGuess[3], tries} )
any_key()--wait for keypress before closing console window.
end if
end procedure
--run the procedure
getInputAndProcess(1)
Output :
The program has thought of a four digit number using only digits 1 to 9. Type your guess and press enter. 7456 Guess #1 : You guessed 7456 . You found 1 bull, 1 cow. Type new guess. 7116 Guess #2 : You guessed 7116 . You found 1 bull, 0 cows. Type new guess. 7862 Guess #3 : You guessed 7862 . You found 0 bulls, 2 cows. Type new guess. 1826 [...etc] 6586 Guess #10 : You guessed 6586 . You found 3 bulls, 0 cows. Type new guess. 5586 Guess #11 : You guessed 5586 . You found 3 bulls, 0 cows. Type new guess. 2586 Guess #12 : You guessed 2586 . You found 3 bulls, 0 cows. Type new guess. 9586 The number was 9586. You guessed 9586 in 13 tries. Press Any Key to continue...
F#
open System
let generate_number targetSize =
let rnd = Random()
let initial = Seq.initInfinite (fun _ -> rnd.Next(1,9))
initial |> Seq.distinct |> Seq.take(targetSize) |> Seq.toList
let countBulls guess target =
let hits = List.map2 (fun g t -> if g = t then true else false) guess target
List.filter (fun x -> x = true) hits |> List.length
let countCows guess target =
let mutable score = 0
for g in guess do
for t in target do
if g = t then
score <- score + 1
else
score <- score
score
let countScore guess target =
let bulls = countBulls guess target
let cows = countCows guess target
(bulls, cows)
let playRound guess target =
countScore guess target
let inline ctoi c : int =
int c - int '0'
let lineToList (line: string) =
let listc = Seq.map(fun c -> c |> string) line |> Seq.toList
let conv = List.map(fun x -> Int32.Parse x) listc
conv
let readLine() =
let line = Console.ReadLine()
if line <> null then
if line.Length = 4 then
Ok (lineToList line)
else
Error("Input guess must be 4 characters!")
else
Error("Input guess cannot be empty!")
let rec handleInput() =
let line = readLine()
match line with
| Ok x -> x
| Error s ->
printfn "%A" s
handleInput()
[<EntryPoint>]
let main argv =
let target = generate_number 4
let mutable shouldEnd = false
while shouldEnd = false do
let guess = handleInput()
let (b, c) = playRound guess target
printfn "Bulls: %i | Cows: %i" b c
if b = 4 then
shouldEnd <- true
else
shouldEnd <- false
0
FreeBASIC
function get_digit( num as uinteger, ps as uinteger ) as uinteger
return (num mod 10^(ps+1))\10^ps
end function
function is_malformed( num as uinteger ) as boolean
if num > 9876 then return true
dim as uinteger i, j
for i = 0 to 2
for j = i+1 to 3
if get_digit( num, j ) = get_digit( num, i ) then return true
next j
next i
return false
end function
function make_number() as uinteger
dim as uinteger num = 0
while is_malformed(num)
num = int(rnd*9877)
wend
return num
end function
randomize timer
dim as uinteger count=0, num=make_number(), guess=0
dim as uinteger cows, bulls, i, j
while guess <> num
count += 1
do
print "Guess a number. "
input guess
loop while is_malformed(guess)
cows = 0
bulls = 0
for i = 0 to 3
for j = 0 to 3
if get_digit( num, i ) = get_digit( guess, j ) then
if i= j then bulls += 1
if i<>j then cows += 1
end if
next j
next i
print using "You scored # bulls and # cows."; bulls; cows
wend
print using "Correct. That took you ### guesses."; count
Factor
idiomatic style:
USING: io kernel math math.parser random ranges sequences sets ; IN: bullsncows
9 [1..b] 4 sample [ 48 + ] "" map-as
[ "guess the 4-digit number: " write flush readln dup
[ length 4 = ] [ [ 48 57 [a..b] in? ] all? ] bi and ! [48,57] is the ascii range for 0-9
[ 2dup =
[ 2drop "yep!" print flush f ]
[ "bulls & cows: " write
[ 0 [ = 1 0 ? + ] 2reduce ] [ intersect length ] 2bi over -
[ number>string ] bi@ " & " glue print flush t ]
if ]
[ 2drop "bad input" print t ]
if ] curry loop
imperative/oop style:
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 ;
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")
}
}
}
FOCAL
01.10 T %1,"BULLS AND COWS"!"----- --- ----"!!
01.20 S T=0;D 3
01.30 D 2;D 5;S T=T+1;T "BULLS",B," COWS",C,!!
01.40 I (B-4)1.3
01.50 T "YOU WON! GUESSES",%4,T,!!
01.60 Q
02.10 A "GUESS",A
02.20 F X=0,3;S B=FITR(A/10);S G(3-X)=A-B*10;S A=B
02.30 S A=1
02.40 F X=0,3;S A=A*G(X)
02.50 I (-A)2.6;T "NEED FOUR NONZERO DIGITS"!;G 2.1
02.60 F X=0,2;F Y=X+1,3;S A=A*(FABS(G(X)-G(Y)))
02.70 I (-A)2.8;T "NO DUPLICATES ALLOWED"!;G 2.1
02.80 R
03.10 F X=0,3;S S(X)=0
03.20 F X=0,3;D 4;S S(X)=A
04.10 S A=10*FRAN();S A=FITR(1+9*(A-FITR(A)))
04.20 S Z=1
04.30 F Y=0,3;S Z=Z*(FABS(A-S(Y)))
04.40 I (-Z)4.5,4.1
04.50 R
05.10 S B=0
05.20 F X=0,3;D 5.6
05.30 S C=-B
05.40 F X=0,3;F Y=0,3;D 5.7
05.50 R
05.60 I (-FABS(S(X)-G(X)))5.5,5.8
05.70 I (-FABS(S(X)-G(Y)))5.5,5.9
05.80 S B=B+1
05.90 S C=C+1
- Output:
BULLS AND COWS ----- --- ---- GUESS:1234 BULLS= 0 COWS= 3 GUESS:3214 BULLS= 1 COWS= 2 GUESS:3124 BULLS= 2 COWS= 1 GUESS:3145 BULLS= 3 COWS= 0 GUESS:3146 BULLS= 3 COWS= 0 GUESS:3147 BULLS= 3 COWS= 0 GUESS:3148 BULLS= 3 COWS= 0 GUESS:3149 BULLS= 4 COWS= 0 YOU WON! GUESSES= 8
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 ;
- Output:
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
Fortran
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
Frink
// Bulls and Cows - Written in Frink
println["Welcome to Bulls and Cows!"]
// Put 4 random digits into target array
digits = array[1 to 9]
target = new array
for i = 0 to 3
{
target@i = digits.removeRandom[]
}
// Game variables
guessCount = 0
solved = 0
while solved == 0
{
// Round variables
bulls = 0
cows = 0
// Input guess from player
guess = input["Guess a 4 digit number with numbers 1 to 9: "]
// Valid Guess Tests. Set validGuess to 1. If any test fails it will be set to 0
validGuess = 1
// Test for exactly 4 digits
if length[guess] != 4
{
println["$guess is invalid. Your guess must be 4 digits."]
validGuess = 0
}
// Test for any characters not in 1 - 9 using regex
if guess =~ %r/[^1-9]/
{
println["$guess is invalid. Your guess can only contain the digits 1 through 9."]
validGuess = 0
}
// Check for duplicate digits in guess
comboCheck = 1
guessArr = charList[guess] // Split guess string into array of characters.
guessArrCombos = guessArr.combinations[2] // Divide the array into all possible 2 digits combinations.
for geussCombo = guessArrCombos
{
if geussCombo@0 == geussCombo@1 // If the two digits in the combinations are the same mark the comboCheck as failed.
comboCheck = 0
}
if comboCheck == 0
{
println["$guess is invalid. Each digit in your guess should be unique."]
validGuess = 0
}
// If all tests pass, continue with the game.
if validGuess == 1
{
guessCount = guessCount + 1
for i = 0 to 3
{
if parseInt[guessArr@i] == target@i // Convert guess from string to int. Frink imports all input as strings.
{
bulls = bulls + 1
next // If bull is found, skip the contains check.
}
if target.contains[parseInt[guessArr@i]]
{
cows = cows + 1
}
}
if bulls == 4
{
solved = 1 // Exit from While loop.
} else
{
// Print the results of the guess. Formatting for plurals.
bullsPlural = bulls == 1 ? "bull" : "bulls"
cowsPlural = cows == 1 ? "cow" : "cows"
println["Your guess of $guess had $bulls $bullsPlural and $cows $cowsPlural."]
}
}
}
guessPlural = guessCount == 1 ? "guess" : "guesses"
println["Congratulations! Your guess of $guess was correct! You solved this in $guessCount $guessPlural."]
- Output:
Welcome to Bulls and Cows! Your guess of 1234 had 1 bull and 2 cows. Your guess of 5678 had 0 bulls and 1 cow. Your guess of 2345 had 0 bulls and 2 cows. Your guess of 3261 had 1 bull and 2 cows. Your guess of 4173 had 0 bulls and 3 cows. Your guess of 8231 had 2 bulls and 0 cows. Your guess of 7134 had 1 bull and 2 cows. Your guess of 3461 had 2 bulls and 2 cows. Congratulations! Your guess of 6431 was correct! You solved this in 9 guesses.
FutureBasic
include "NSLog.incl"
str15 guess, goal
short x, y
cgRect wndrect
begin enum 1
_window
_bullLabel
_cowLabel
_horzLine
_vertLine
_newGameBtn
_alert = 101
end enum
void local fn showStr( string as str15 )
short r
x = 20
for r = 1 to string[0]
print %(x,y)chr$( string[r] );
x += 39
next
end fn
void local fn NewGame
str15 ch
goal = "" : guess = "" :y = 20
window _window,,wndRect
text ,,fn colorRed
cls
fn showStr( "????" )
do
ch = chr$(rnd(9) or _"0")
if instr$(0, goal, ch) == 0 then goal += ch
until goal[0] == 4
nslog(@"%u",val&(goal)) //unrem for testing
y += 48
end fn
local fn SetWindowFrame
CGRect r = fn WindowContentRect( _window )
r.size.height += 32
r.origin.y -= 32
window _window,,r
if ( r.origin.y < 150 )
alert _alert,, @"Too many guesses!",, @"Give up", YES
fn newGame
end if
end fn
local fn play( ch as str15 )
short r, bulls = 0, cows = 0
if instr$(0, guess, ch) then exit fn
guess += ch
text,,fn colorDarkGray
fn showStr( guess )
if guess[0] < 4 then exit fn
for r = 1 to 4
if goal[r] == guess[r] then bulls++ : continue
if instr$(0, goal, chr$(guess[r]) ) then cows++
next
select
case bulls == 4
text ,,fn colorRed
print %(x + 31, y)("W I N!")
y = 20 : fn showStr( goal )
case else : print %(x + 35, y)bulls;" "; cows
y += 32 : guess = ""
end select
fn SetWindowFrame
end fn
void local fn BuildWindow
subclass window _window, @"Bulls and cows", (0,0,311,114), NSWindowStyleMaskTitled + NSWindowStyleMaskClosable
wndrect = = fn WindowContentRect( _window )
textlabel _bullLabel, @"🐂", (198,59,38,40)
textlabel _cowLabel, @"🐄", (255,59,38,40)
ControlSetFontWithName( _bullLabel, NULL, 30 )
ControlSetFontWithName( _cowLabel, NULL, 30 )
box _horzLine,, (12,50,287,5), NSBoxSeparator
box _vertLine,, (180,12,5,90), NSBoxSeparator
ViewSetAutoresizingMask( _vertLine, NSViewHeightSizable )
button _newGameBtn,,, @"New Game", (198,13,100,32)
ViewSetAutoresizingMask( _newGameBtn, NSViewMaxYMargin )
text @"menlo bold",24,,fn ColorWindowBackground
end fn
void local fn DoDialog( evt as long, tag as long )
select ( evt )
case _windowKeyDown //: stop
short ch = intval( fn EventCharacters )
if ch then fn play( chr$( ch or _"0" ) ):DialogEventSetBool(YES)
case _btnClick : fn NewGame
case _windowWillClose : end
end select
end fn
on dialog fn DoDialog
fn buildWindow
fn newGame
HandleEvents
- Output:
File:Bulls and Cows in FutureBasic.png
Go
package main
import (
"bufio"
"bytes"
"fmt"
"math/rand"
"os"
"strings"
"time"
)
func main() {
fmt.Println(`Cows and Bulls
Guess four digit number of unique digits in the range 1 to 9.
A correct digit but not in the correct place is a cow.
A correct digit in the correct place is a bull.`)
// generate pattern
pat := make([]byte, 4)
rand.Seed(time.Now().Unix())
r := rand.Perm(9)
for i := range pat {
pat[i] = '1' + byte(r[i])
}
// accept and score guesses
valid := []byte("123456789")
guess:
for in := bufio.NewReader(os.Stdin); ; {
fmt.Print("Guess: ")
guess, err := in.ReadString('\n')
if err != nil {
fmt.Println("\nSo, bye.")
return
}
guess = strings.TrimSpace(guess)
if len(guess) != 4 {
// malformed: not four characters
fmt.Println("Please guess a four digit number.")
continue
}
var cows, bulls int
for ig, cg := range guess {
if strings.IndexRune(guess[:ig], cg) >= 0 {
// malformed: repeated digit
fmt.Printf("Repeated digit: %c\n", cg)
continue guess
}
switch bytes.IndexByte(pat, byte(cg)) {
case -1:
if bytes.IndexByte(valid, byte(cg)) == -1 {
// malformed: not a digit
fmt.Printf("Invalid digit: %c\n", cg)
continue guess
}
default: // I just think cows should go first
cows++
case ig:
bulls++
}
}
fmt.Printf("Cows: %d, bulls: %d\n", cows, bulls)
if bulls == 4 {
fmt.Println("You got it.")
return
}
}
}
Golo
#!/usr/bin/env golosh
----
This module is the Bulls and Cows game.
----
module Bullsandcows
import gololang.Decorators
import gololang.Functions
import gololang.IO
import java.util
function main = |args| {
while true {
let secret = create4RandomNumbers()
println("Welcome to Bulls And Cows")
while true {
println("Please enter a 4 digit number")
println("(with only the digits 1 to 9 and no repeated digits, for example 2537)")
let guess = readln("guess: ")
let result = validateGuess(guess)
if result: isValid() {
let bulls, cows = bullsAndOrCows(result: digits(), secret)
if bulls is 4 {
println("You win!")
break
}
println("bulls: " + bulls)
println("cows: " + cows)
} else {
println(result: message())
}
}
}
}
function create4RandomNumbers = {
let numbers = vector[1, 2, 3, 4, 5, 6, 7, 8, 9]
Collections.shuffle(numbers)
let shuffled = numbers: subList(0, 4)
return shuffled
}
union Result = {
Valid = { digits }
Invalid = { message }
}
@checkArguments(isString())
function validateGuess = |guess| {
var digits = []
try {
let number = guess: toInt()
digits = number: digits()
if digits: exists(|d| -> d is 0) {
return Result.Invalid("No zeroes please")
}
if digits: size() isnt 4 {
return Result.Invalid("Four digits please")
}
let digitSet = set[ digit foreach digit in digits ]
if digitSet: size() < digits: size() {
return Result.Invalid("No duplicate numbers please")
}
} catch(e) {
return Result.Invalid("Numbers only please")
}
return Result.Valid(digits)
}
let is4Vector = |arg| -> arg oftype java.util.List.class and arg: size() is 4
@checkArguments(is4Vector, is4Vector)
function bullsAndOrCows = |guess, secret| {
var bulls = 0
var cows = 0
foreach i in [0..4] {
let guessNum = guess: get(i)
let secretNum = secret: get(i)
if guessNum is secretNum {
bulls = bulls + 1
} else if secret: exists(|num| -> guessNum is num) {
cows = cows + 1
}
}
return [bulls, cows]
}
augment java.lang.Integer {
function digits = |this| {
var remaining = this
let digits = vector[]
while remaining > 0 {
digits: prepend(remaining % 10)
remaining = remaining / 10
}
return digits
}
}
Groovy
class BullsAndCows {
static void main(args) {
def inputReader = System.in.newReader()
def numberGenerator = new Random()
def targetValue
while (targetValueIsInvalid(targetValue = numberGenerator.nextInt(9000) + 1000)) continue
def targetStr = targetValue.toString()
def guessed = false
def guesses = 0
while (!guessed) {
def bulls = 0, cows = 0
print 'Guess a 4-digit number with no duplicate digits: '
def guess = inputReader.readLine()
if (guess.length() != 4 || !guess.isInteger() || targetValueIsInvalid(guess.toInteger())) {
continue
}
guesses++
4.times {
if (targetStr[it] == guess[it]) {
bulls++
} else if (targetStr.contains(guess[it])) {
cows++
}
}
if (bulls == 4) {
guessed = true
} else {
println "$cows Cows and $bulls Bulls."
}
}
println "You won after $guesses guesses!"
}
static targetValueIsInvalid(value) {
def digitList = []
while (value > 0) {
if (digitList[value % 10] == 0 || digitList[value % 10]) {
return true
}
digitList[value % 10] = true
value = value.intdiv(10)
}
false
}
}
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
Hy
(import random)
(def +size+ 4)
(def +digits+ "123456789")
(def +secret+ (random.sample +digits+ +size+))
(while True
(while True
(setv guess (list (distinct (raw-input "Enter a guess: "))))
(when (and
(= (len guess) +size+)
(all (map (fn [c] (in c +digits+)) guess)))
(break))
(print "Malformed guess; try again"))
(setv bulls 0)
(setv cows 0)
(for [i (range +size+)] (cond
[(= (get guess i) (get +secret+ i)) (setv bulls (inc bulls))]
[(in (get guess i) +secret+) (setv cows (inc cows))]))
(when (= bulls +size+)
(break))
(print (.format "{} bull{}, {} cows"
bulls (if (= bulls 1) "" "s")
cows (if (= cows 1) "" "s"))))
(print "A winner is you!")
Icon and Unicon
The following works in both Icon and Unicon.
procedure main()
digits := "123456789"
every !digits :=: ?digits
num := digits[1+:4]
repeat if score(num, getGuess(num)) then break
write("Good job.")
end
procedure getGuess(num)
repeat {
writes("Enter a guess: ")
guess := read() | stop("Quitter!")
if *(guess ** '123456789') == *num then return guess
write("Malformed guess: ",guess,". Try again.")
}
end
procedure score(num, guess)
bulls := 0
cows := *(num ** guess)
every (num[i := 1 to *num] == guess[i], bulls +:= 1, cows -:= 1)
write("\t",bulls," bulls and ",cows," cows")
return (bulls = *num)
end
J
A tacit recursive functional version. To play, call moo
with a dummy argument.
output=. [ 'Bulls: '&,:@'Cows: ' echo@,. ":@,.
valid =. *./@e.&'0123456789' *. 4 = #
guess =. [: ".&> :: ] $:^:(-.@valid)@(1!:1@1)@echo@'Guess:'
game =. [ $:^:(4 0-.@-:]) [ (+/@:= output@, e.+/@:*.~:) guess
moo =. 'You win!'[ (1+4?9:) game ]
An expanded version that uses iteration instead of recursion:
U =. [ F.([.[(_2:Z:].)) NB. u until v
input =. 1!:1@1@echo@'Guess: '
output =. [ ('Bulls: ',:'Cows: ')echo@,.":@,.
isdigits=. *./@e.&'0123456789'
valid =. isdigits*.4=#
guess =. [:".&>input U(valid@])
bulls =. +/@:=
cows =. [:+/e.*.~:
game =. ([:output [(bulls,cows) guess)U(4 0-:])
random =. 1+4?9:
moo =. 'You win!'[ random game ]
Fold (F.
) is used instead of Until=. [.^:(-.@:].)^:_
because the latter would exit the loop if two consecutive iterations produced the same output.
In real applications, a.&i.-48"_
should be used instead of ".
to safely convert character input to a numeric array.
A version that uses imperative control flow:
require 'misc'
plural=: conjunction define
(":m),' ',n,'s'#~1~:m
)
bullcow=:monad define
number=. 1+4?9
whilst. -.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'
)
For example:
bullcow''
Guess my number: 1234
0 bulls and 1 cow.
Guess my number: 5678
3 bulls and 0 cows.
Guess my number: 2349
0 bulls and 0 cows.
Guess my number: 1567
0 bulls and 3 cows.
Guess my number: 6178
3 bulls and 0 cows.
Guess my number: 6157
1 bull and 2 cows.
Guess my number: 5178
4 bulls and 0 cows.
you win
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;
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!
JavaScript
Spidermonkey version
#!/usr/bin/env js
function main() {
var len = 4;
playBullsAndCows(len);
}
function playBullsAndCows(len) {
var num = pickNum(len);
// print('The secret number is:\n ' + num.join('\n '));
showInstructions(len);
var nGuesses = 0;
while (true) {
nGuesses++;
var guess = getGuess(nGuesses, len);
var census = countBovine(num, guess);
showScore(census.bulls, census.cows);
if (census.bulls == len) {
showFinalResult(nGuesses);
return;
}
}
}
function showScore(nBulls, nCows) {
print(' Bulls: ' + nBulls + ', cows: ' + nCows);
}
function showFinalResult(guesses) {
print('You win!!! Guesses needed: ' + guesses);
}
function countBovine(num, guess) {
var count = {bulls:0, cows:0};
var g = guess.join('');
for (var i = 0; i < num.length; i++) {
var digPresent = g.search(num[i]) != -1;
if (num[i] == guess[i]) count.bulls++;
else if (digPresent) count.cows++;
}
return count;
}
function getGuess(nGuesses, len) {
while (true) {
putstr('Your guess #' + nGuesses + ': ');
var guess = readline();
guess = String(parseInt(guess)).split('');
if (guess.length != len) {
print(' You must enter a ' + len + ' digit number.');
continue;
}
if (hasDups(guess)) {
print(' No digits can be duplicated.');
continue;
}
return guess;
}
}
function hasDups(ary) {
var t = ary.concat().sort();
for (var i = 1; i < t.length; i++) {
if (t[i] == t[i-1]) return true;
}
return false;
}
function showInstructions(len) {
print();
print('Bulls and Cows Game');
print('-------------------');
print(' You must guess the ' + len + ' digit number I am thinking of.');
print(' The number is composed of the digits 1-9.');
print(' No digit appears more than once.');
print(' After each of your guesses, I will tell you:');
print(' The number of bulls (digits in right place)');
print(' The number of cows (correct digits, but in the wrong place)');
print();
}
function pickNum(len) {
var nums = [1, 2, 3, 4, 5, 6, 7, 8, 9];
nums.sort(function(){return Math.random() - 0.5});
return nums.slice(0, len);
}
main();
Example game (cheating!):
Bulls and Cows Game ------------------- You must guess the 4 digit number I am thinking of. The number is composed of the digits 1-9. No digit appears more than once. After each of your guesses, I will tell you: The number of bulls (digits in right place) The number of cows (correct digits, but in wrong place) Your guess #1: 1234 Bulls: 0, cows: 2 Your guess #2: 5678 Bulls: 1, cows: 1 Your guess #3: 3167 Bulls: 0, cows: 3 Your guess #4: 9123 Bulls: 1, cows: 1 Your guess #5: 5137 Bulls: 1, cows: 3 Your guess #6: 5317 Bulls: 2, cows: 2 Your guess #7: 5731 Bulls: 2, cows: 2 Your guess #8: 5713 Bulls: 4, cows: 0 You win! Guesses needed: 8
jq
Also works with gojq, the Go implementation of jq.
Adapted from Wren
The following program reads the user's input from STDIN, and reads random digits from /dev/random using the --slurpfile command-line option. This makes the program more convoluted than would have been the case had the generation of the initial four-digit pseudo-random integer been done in a separate step, but it does illustrate how the limitations of jq's I/O can be circumvented in this case.
In a bash or bash-like environment, a suitable invocation would be as follows:
jq -nrR --slurpfile raw <(< /dev/random tr -cd '0-9' | fold -w 1 | head -n 100) -f bc.jq
bc.jq
# A PRNG for generating a pseudo-random integer in range(0; .).
# $array must be a sufficiently large array of pseudo-random integers in range(0;10).
# $start specifies the position in $array to begin searching.
# Output: {prn, start) where .prn is a PRN in range(0; .) and .start is the corresponding position in $array.
def prn($array; $start):
def a2n: map(tostring) | join("") | tonumber;
if . == 1 then 0
else . as $n
| (($n-1)|tostring|length) as $w
| {$start}
| until( $array[.start: .start + $w] | a2n < $n; .start+=1 )
| {start, prn: ($raw[.start: .start + $w] | a2n)}
end;
# Generate a 4-digit PRN from 1234 to 9876 inclusive, with no zeros or repeated digits.
# Global variable: $raw (see documentation for $array above)
def num:
def _num($start):
(8643|prn($raw; $start)) as $prn
| (1234 + $prn.prn)
| . as $n
| tostring
| if (test("0")|not) and ((explode|unique|length) == 4)
then $n
else _num($prn.start+4)
end;
_num(0);
def MAX_GUESSES: 20; # say
def instructions:
"All guesses should have exactly 4 distinct digits excluding zero.",
"Keep guessing until you guess the chosen number (maximum \(MAX_GUESSES) valid guesses).\n";
def play:
num as $num
| ($num|tostring|explode) as $numArray
| { guesses: 0 }
| instructions, "Enter your guess:",
(label $out
| foreach range(0; infinite) as $i (.;
if .bulls == 4 or .guesses == MAX_GUESSES then break $out
else .guess = input
| if .guess == $num then .emit = "You have won with \(.guesses+1) valid guesses!"
else .n = (.guess | try tonumber catch null)
| if .n == null then .emit = "Not a valid number"
elif .guess|test("[+-.]") then .emit = "The guess should not contain a sign or decimal point."
elif .guess|test("0") then .emit = "The guess cannot contain zero."
elif .guess|length != 4 then .emit = "The guess must have exactly 4 digits."
else .guessArray = (.guess | explode )
| if .guessArray | unique | length < 4 then .emit = "All digits must be distinct."
else . + {bulls: 0, cows: 0 }
| reduce range(0; .guessArray|length) as $i ( .;
if $numArray[$i] == .guessArray[$i] then .bulls += 1
elif (.guessArray[$i] | IN($numArray[])) then .cows += 1
else .
end)
| .emit = "Your score for this guess: Bulls = \(.bulls) Cows = \(.cows)"
| .guesses += 1
end
end
end
end;
select(.emit).emit,
if .bulls == 4 then "Congratulations!"
elif .guesses == MAX_GUESSES
then "\nYou have now had \(.guesses) valid guesses, the maximum allowed. Bye!"
else "Enter your next guess:"
end ) );
play
Julia
function cowsbulls()
print("Welcome to Cows & Bulls! I've picked a number with unique digits between 1 and 9, go ahead and type your guess.\n
You get one bull for every right number in the right position.\n
You get one cow for every right number, but in the wrong position.\n
Enter 'n' to pick a new number and 'q' to quit.\n>")
function new_number()
s = [1:9]
n = ""
for i = 9:-1:6
n *= string(delete!(s,rand(1:i)))
end
return n
end
answer = new_number()
while true
input = chomp(readline(STDIN))
input == "q" && break
if input == "n"
answer = new_number()
print("\nI've picked a new number, go ahead and guess\n>")
continue
end
!ismatch(r"^[1-9]{4}$",input) && (print("Invalid guess: Please enter a 4-digit number\n>"); continue)
if input == answer
print("\nYou're right! Good guessing!\nEnter 'n' for a new number or 'q' to quit\n>")
else
bulls = sum(answer.data .== input.data)
cows = sum([answer[x] != input[x] && contains(input.data,answer[x]) for x = 1:4])
print("\nNot quite! Your guess is worth:\n$bulls Bulls\n$cows Cows\nPlease guess again\n\n>")
end
end
end
The following version checks thoroughly that the input of the player is constituted of four distincts digits.
function bullsandcows ()
bulls = cows = turns = 0
result = (s = [] ; while length(unique(s))<4 push!(s,rand('1':'9')) end; unique(s))
println("A game of bulls and cows!")
while (bulls != 4)
print("Your guess? ")
guess = collect(chomp(readline(STDIN)))
if ! (length(unique(guess)) == length(guess) == 4 && all(isdigit,guess))
println("please, enter four distincts digits")
continue
end
bulls = sum(map(==, guess, result))
cows = length(intersect(guess,result)) - bulls
println("$bulls bulls and $cows cows!") ; turns += 1
end
println("You win! You succeeded in $turns guesses.")
end
- Output:
julia> bullsandcows() A game of bulls and cows! Your guess? 1234 0 bulls and 2 cows! Your guess? 12334 please, enter four distincts digits Your guess? 5678 1 bulls and 1 cows! Your guess? 1111 please, enter four distincts digits Your guess? grr please, enter four distincts digits Your guess? ... please, enter four distincts digits Your guess?
K
run in ngn/k.
n:1+-4?9
loop:{
`1:"guess: ";g:(`i$-1_1:`)-48 / -48 to convert ascii digit codepoints to corresponding int values
$[n~g;[`0:"yup!";`exit 0]
(4=#g)&*/(g<10)&~g<0;`0:"bulls & cows: "," & "/$(b;(#g^g^n)-b:+/n=g)
`0:"bad input"]}
{1}loop/0 / "while true: loop". 0 is a dummy arg
Kotlin
const val MAX_GUESSES = 20 // say
fun main() {
val num = ('1'..'9').shuffled().take(4).joinToString("")
println("All guesses should have exactly 4 distinct digits excluding zero.")
println("Keep guessing until you guess the chosen number (maximum $MAX_GUESSES valid guesses).\n")
var guesses = 0
while (true) {
print("Enter your guess : ")
val guess = readln().trim()
if (guess == num) {
println("You've won with ${++guesses} valid guesses!")
break
}
val n = guess.toIntOrNull()
if (n == null)
println("Not a valid number")
else if ('-' in guess || '+' in guess)
println("Can't contain a sign")
else if ('0' in guess)
println("Can't contain zero")
else if (guess.length != 4)
println("Must have exactly 4 digits")
else if (guess.toSet().size < 4)
println("All digits must be distinct")
else {
var bulls = 0
var cows = 0
for ((i, c) in guess.withIndex()) {
if (num[i] == c) bulls++
else if (c in num) cows++
}
println("Your score for this guess: Bulls = $bulls Cows = $cows")
guesses++
if (guesses == MAX_GUESSES)
println("You've now had $guesses valid guesses, the maximum allowed")
}
}
}
Sample input/output:
- Output:
Enter your guess : 1234 Your score for this guess: Bulls = 0 Cows = 2 Enter your guess : 1256 Your score for this guess: Bulls = 0 Cows = 2 Enter your guess : 2178 Your score for this guess: Bulls = 1 Cows = 0 Enter your guess : 2519 Your score for this guess: Bulls = 3 Cows = 0 Enter your guess : 2569 Your score for this guess: Bulls = 3 Cows = 0 Enter your guess : 2579 Your score for this guess: Bulls = 3 Cows = 0 Enter your guess : 2589 Your score for this guess: Bulls = 3 Cows = 0 Enter your guess : 2539 Your score for this guess: Bulls = 3 Cows = 0 Enter your guess : 2549 You've won with 9 valid guesses!
Lasso
This game uses an HTML form to submit the answer. The random number and history are stored in a session using Lasso's built in session management.
[
define randomizer() => {
local(n = string)
while(#n->size < 4) => {
local(r = integer_random(1,9)->asString)
#n !>> #r ? #n->append(#r)
}
return #n
}
define cowbullchecker(n::string,a::string) => {
integer(#n) == integer(#a) ? return (:true,map('cows'=0,'bulls'=4,'choice'=#a))
local(cowbull = map('cows'=0,'bulls'=0,'choice'=#a),'checked' = array)
loop(4) => {
if(#checked !>> integer(#a->values->get(loop_count))) => {
#checked->insert(integer(#a->values->get(loop_count)))
if(integer(#n->values->get(loop_count)) == integer(#a->values->get(loop_count))) => {
#cowbull->find('bulls') += 1
else(#n->values >> #a->values->get(loop_count))
#cowbull->find('cows') += 1
}
}
}
#cowbull->find('bulls') == 4 ? return (:true,map('cows'=0,'bulls'=4,'choice'=#a))
return (:true,#cowbull)
}
session_start('user')
session_addvar('user', 'num')
session_addvar('user', 'historic_choices')
// set up rand
var(num)->isNotA(::string) ? var(num = randomizer)
var(historic_choices)->isNotA(::array) ? var(historic_choices = array)
local(success = false)
// check answer
if(web_request->param('a')->asString->size) => {
local(success,result) = cowbullchecker($num,web_request->param('a')->asString)
$historic_choices->insert(#result)
}
if(web_request->params->asStaticArray >> 'restart') => {
$num = randomizer
$historic_choices = array
}
]
<h1>Bulls and Cows</h1>
<p>Guess the 4-digit number...</p>
<p>Your win if the guess is the same as the randomly chosen number.<br>
- A score of one bull is accumulated for each digit in your guess that equals the corresponding digit in the randomly chosen initial number.<br>
- A score of one cow is accumulated for each digit in your guess that also appears in the randomly chosen number, but in the wrong position.
</p>
[
local(win = false)
if($historic_choices->size) => {
with c in $historic_choices do => {^
'<p>'+#c->find('choice')+': Bulls: '+#c->find('bulls')+', Cows: '+#c->find('cows')
if(#c->find('bulls') == 4) => {^
' - YOU WIN!'
#win = true
^}
'</p>'
^}
}
if(not #win) => {^
]
<form action="?" method="post">
<input name="a" value="[web_request->param('a')->asString]" size="5">
<input type="submit" name="guess">
<a href="?restart">Restart</a>
</form>
[else
'<a href="?restart">Restart</a>'
^}]
- Output:
Game in progress:
Bulls and Cows Guess the 4-digit number... Your win if the guess is the same as the randomly chosen number. - A score of one bull is accumulated for each digit in your guess that equals the corresponding digit in the randomly chosen initial number. - A score of one cow is accumulated for each digit in your guess that also appears in the randomly chosen number, but in the wrong position. 4567: Bulls: 0, Cows: 1 4567: Bulls: 0, Cows: 1 (input box) (submit button) Restart
- Output:
Game in to completion:
Bulls and Cows Guess the 4-digit number... Your win if the guess is the same as the randomly chosen number. - A score of one bull is accumulated for each digit in your guess that equals the corresponding digit in the randomly chosen initial number. - A score of one cow is accumulated for each digit in your guess that also appears in the randomly chosen number, but in the wrong position. 1234: Bulls: 0, Cows: 2 1256: Bulls: 0, Cows: 1 1789: Bulls: 0, Cows: 1 1222: Bulls: 0, Cows: 0 3456: Bulls: 1, Cows: 2 3564: Bulls: 0, Cows: 3 3567: Bulls: 0, Cows: 2 8564: Bulls: 0, Cows: 2 3564: Bulls: 0, Cows: 3 4365: Bulls: 0, Cows: 3 5436: Bulls: 2, Cows: 1 5478: Bulls: 2, Cows: 0 5463: Bulls: 3, Cows: 0 5468: Bulls: 2, Cows: 0 5493: Bulls: 4, Cows: 0 - YOU WIN! Restart
Liberty BASIC
do while len( secret$) <4
c$ =chr$( int( rnd( 1) *9) +49)
if not( instr( secret$, c$)) then secret$ =secret$ +c$
loop
print " Secret number has been guessed.... "; secret$
guesses = 0
[loop]
print " Your guess ";
input " "; guess$
guesses = guesses +1
r$ =score$( guess$, secret$)
bulls =val( word$( r$, 1, ","))
cows =val( word$( r$, 2, ","))
print " Result: "; bulls; " bulls, and "; cows; " cows"
print
if guess$ =secret$ then
print " You won after "; guesses; " guesses!"
print " You guessed it in "; guesses
print " Thanks for playing!"
wait
end if
goto [loop]
end ' _____________________________________________________________
function check( i$) ' check =0 if no digit repeats, else =1
check =0
for i =1 to 3
for j =i +1 to 4
if mid$( i$, i, 1) =mid$( i$, j, 1) then check =1
next j
next i
end function
function score$( a$, b$) ' return as a csv string the number of bulls & cows.
bulls = 0: cows = 0
for i = 1 to 4
c$ = mid$( a$, i, 1)
if mid$( b$, i, 1) = c$ then
bulls = bulls + 1
else
if instr( b$, c$) <>0 and instr( b$, c$) <>i then
cows = cows + 1
end if
end if
next i
score$ =str$( bulls); ","; str$( cows)
end function
[quit]
close #w
end
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
Lua
function ShuffleArray(array)
for i=1,#array-1 do
local t = math.random(i, #array)
array[i], array[t] = array[t], array[i]
end
end
function GenerateNumber()
local digits = {1,2,3,4,5,6,7,8,9}
ShuffleArray(digits)
return digits[1] * 1000 +
digits[2] * 100 +
digits[3] * 10 +
digits[4]
end
function IsMalformed(input)
local malformed = false
if #input == 4 then
local already_used = {}
for i=1,4 do
local digit = input:byte(i) - string.byte('0')
if digit < 1 or digit > 9 or already_used[digit] then
malformed = true
break
end
already_used[digit] = true
end
else
malformed = true
end
return malformed
end
math.randomseed(os.time())
math.randomseed(math.random(2^31-1)) -- since os.time() only returns seconds
print("\nWelcome to Bulls and Cows!")
print("")
print("The object of this game is to guess the random 4-digit number that the")
print("computer has chosen. The number is generated using only the digits 1-9,")
print("with no repeated digits. Each time you enter a guess, you will score one")
print("\"bull\" for each digit in your guess that matches the corresponding digit")
print("in the computer-generated number, and you will score one \"cow\" for each")
print("digit in your guess that appears in the computer-generated number, but is")
print("in the wrong position. Use this information to refine your guesses. When")
print("you guess the correct number, you win.");
print("")
quit = false
repeat
magic_number = GenerateNumber()
magic_string = tostring(magic_number) -- Easier to do scoring with a string
repeat
io.write("\nEnter your guess (or 'Q' to quit): ")
user_input = io.read()
if user_input == 'Q' or user_input == 'q' then
quit = true
break
end
if not IsMalformed(user_input) then
if user_input == magic_string then
print("YOU WIN!!!")
else
local bulls, cows = 0, 0
for i=1,#user_input do
local find_result = magic_string:find(user_input:sub(i,i))
if find_result and find_result == i then
bulls = bulls + 1
elseif find_result then
cows = cows + 1
end
end
print(string.format("You scored %d bulls, %d cows", bulls, cows))
end
else
print("Malformed input. You must enter a 4-digit number with")
print("no repeated digits, using only the digits 1-9.")
end
until user_input == magic_string
if not quit then
io.write("\nPress <Enter> to play again or 'Q' to quit: ")
user_input = io.read()
if user_input == 'Q' or user_input == 'q' then
quit = true
end
end
if quit then
print("\nGoodbye!")
end
until quit
Another version:
function createNewNumber ()
math.randomseed(os.time())
local numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9}
local tNumb = {} -- list of numbers
for i = 1, 4 do
table.insert(tNumb, math.random(#tNumb+1), table.remove(numbers, math.random(#numbers)))
end
return tNumb
end
TNumber = createNewNumber ()
print ('(right number: ' .. table.concat (TNumber) .. ')')
function isValueInList (value, list)
for i, v in ipairs (list) do
if v == value then return true end
end
return false
end
local nGuesses = 0
while not GameOver do
nGuesses = nGuesses + 1
print("Enter your guess (or 'q' to quit): ")
local input
while not input do
input = io.read()
end
if input == "q" then
GameOver = true
return
end
local tInput = {}
for i=1, string.len(input) do
local number = tonumber(string.sub(input,i,i))
if number and not isValueInList (number, tInput) then
table.insert (tInput, number)
end
end
local malformed = false
if not (string.len(input) == 4) or not (#tInput == 4) then
print (nGuesses, 'bad input: too short or too long')
malformed = true
end
if not malformed then
print (nGuesses, 'parsed input:', table.concat(tInput, ', '))
local nBulls, nCows = 0, 0
for i, number in ipairs (tInput) do
if TNumber[i] == number then
nBulls = nBulls + 1
elseif isValueInList (number, TNumber) then
nCows = nCows + 1
end
end
print (nGuesses, 'Bulls: '.. nBulls .. ' Cows: ' .. nCows)
if nBulls == 4 then
print (nGuesses, 'Win!')
GameOver = true
end
end
end
M2000 Interpreter
Module Game {
Malformed=lambda (a$)->{
=true
if len(a$)<>4 then exit
n=0 : dummy=val(a$,"int",n)
if n<>5 or dummy=0 then exit
for i=1 to 9
if len(filter$(a$,str$(i,0)))<3 then break
next i
=false
}
BullsAndCows$=lambda$ (a$, b$, &ok) ->{
Def b, c
for i=1 to 4
if mid$(a$,i,1)=mid$(b$,i,1) then
b++
else.if instr(b$,mid$(a$,i,1))>0 then
c++
end if
next i
ok=b=4
=format$("bulls {0}, cows {1}", b, c)
}
Random$=lambda$ ->{
def repl$, bank$, c$
bank$="123456789"
for i=1 to 4
c$=mid$(bank$,random(1,len(bank$)),1)
bank$=filter$(bank$, c$)
repl$+=c$
next i
=repl$
}
target$=Random$()
def boolean win=false, a$
do
do
Input "Next guess ";a%
a$=str$(a%,0)
if Malformed(a$) then Print "Malformed input, try again" else exit
always
Print BullsAndCows$(a$, target$, &win)
if win then exit
Print "Bad guess! (4 unique digits, 1-9)"
always
Print "You guess it"
}
Game
Maple
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:
- Output:
Please enter a 4 digit integer with no repeating digits Guess 1: [1, 2, 3, 4] 1 Cow, 1 Bull. Please enter a 4 digit integer with no repeating digits Guess 2: [2, 3, 4, 5] 0 Cows, 1 Bull. ...
Mathematica /Wolfram Language
digits=Last@FixedPointList[If[Length@Union@#==4,#,Table[Random[Integer,{1,9}],{4}]]&,{}]
codes=ToCharacterCode[StringJoin[ToString/@digits]];
Module[{r,bulls,cows},
While[True,
r=InputString[];
If[r===$Canceled,Break[],
With[{userCodes=ToCharacterCode@r},
If[userCodes===codes,Print[r<>": You got it!"];Break[],
If[Length@userCodes==Length@codes,
bulls=Count[userCodes-codes,0];cows=Length@Intersection[codes,userCodes]-bulls;
Print[r<>": "<>ToString[bulls]<>"bull(s), "<>ToString@cows<>"cow(s)."],
Print["Guess four digits."]]]]]]]
Output:
{8, 2, 6, 1} 3432: 0 bull(s), 1 cow(s). Illegal input. 8261: You got it!
MATLAB
function BullsAndCows
% Plays the game Bulls and Cows as the "game master"
% Create a secret number
nDigits = 4;
lowVal = 1;
highVal = 9;
digitList = lowVal:highVal;
secret = zeros(1, 4);
for k = 1:nDigits
idx = randi(length(digitList));
secret(k) = digitList(idx);
digitList(idx) = [];
end
% Give game information
fprintf('Welcome to Bulls and Cows!\n')
fprintf('Try to guess the %d-digit number (no repeated digits).\n', nDigits)
fprintf('Digits are between %d and %d (inclusive).\n', lowVal, highVal)
fprintf('Score: 1 Bull per correct digit in correct place.\n')
fprintf(' 1 Cow per correct digit in incorrect place.\n')
fprintf('The number has been chosen. Now it''s your moooooove!\n')
gs = input('Guess: ', 's');
% Loop until user guesses right or quits (no guess)
nGuesses = 1;
while gs
gn = str2double(gs);
if isnan(gn) || length(gn) > 1 % Not a scalar
fprintf('Malformed guess. Keep to valid scalars.\n')
gs = input('Try again: ', 's');
else
g = sprintf('%d', gn) - '0';
if length(g) ~= nDigits || any(g < lowVal) || any(g > highVal) || ...
length(unique(g)) ~= nDigits % Invalid number for game
fprintf('Malformed guess. Remember:\n')
fprintf(' %d digits\n', nDigits)
fprintf(' Between %d and %d inclusive\n', lowVal, highVal)
fprintf(' No repeated digits\n')
gs = input('Try again: ', 's');
else
score = CountBullsCows(g, secret);
if score(1) == nDigits
fprintf('You win! Bully for you! Only %d guesses.\n', nGuesses)
gs = '';
else
fprintf('Score: %d Bulls, %d Cows\n', score)
gs = input('Guess: ', 's');
end
end
end
nGuesses = nGuesses+1; % Counts malformed guesses
end
end
function score = CountBullsCows(guess, correct)
% Checks the guessed array of digits against the correct array to find the score
% Assumes arrays of same length and valid numbers
bulls = guess == correct;
cows = ismember(guess(~bulls), correct);
score = [sum(bulls) sum(cows)];
end
- Output:
Welcome to Bulls and Cows! Try to guess the 4-digit number (no repeated digits). Digits are between 1 and 9 (inclusive). Score: 1 Bull per correct digit in correct place. 1 Cow per correct digit in incorrect place. The number has been chosen. Now it's your moooooove! Guess: 1234 Score: 0 Bulls, 2 Cows Guess: 2156 Score: 0 Bulls, 1 Cows Guess: 7819 Score: 0 Bulls, 1 Cows Guess: 3457 Score: 0 Bulls, 2 Cows Guess: hello Malformed guess. Keep to valid scalars. Try again: 1123 Malformed guess. Remember: 4 digits Between 1 and 9 inclusive No repeated digits Try again: 34567 Malformed guess. Remember: 4 digits Between 1 and 9 inclusive No repeated digits Try again: 4368 You win! Bully for you! Only 8 guesses.
MAXScript
numCount = 4 -- number of digits to use
digits = #(1, 2, 3, 4, 5, 6, 7, 8, 9)
num = ""
while num.count < numCount and digits.count > 0 do
(
local r = random 1 digits.count
append num (digits[r] as string)
deleteitem digits r
)
digits = undefined
numGuesses = 0
inf = "Rules: \n1. Choose only % unique digits in any combination"+\
" (0 can't be used).\n2. Only positive integers are allowed."+\
"\n3. For each digit that is in it's place, you get a bull,\n"+\
"\tand for each digit that is not in it's place, you get a cow."+\
"\n4. The game is won when your number matches the number I chose."+\
"\n\nPress [esc] to quit the game.\n\n"
clearlistener()
format inf num.count
while not keyboard.escpressed do
(
local userVal = getkbvalue prompt:"\nEnter your number: "
if (userVal as string) == num do
(
format "\nCorrect! The number is %. It took you % moves.\n" num numGuesses
exit with OK
)
local bulls = 0
local cows = 0
local badInput = false
case of
(
(classof userVal != integer):
(
format "\nThe number must be a positive integer.\n"
badInput = true
)
((userVal as string).count != num.count):
(
format "\nThe number must have % digits.\n" num.count
badInput = true
)
((makeuniquearray (for i in 1 to (userVal as string).count \
collect (userVal as string)[i])).count != (userVal as string).count):
(
format "\nThe number can only have unique digits.\n"
badInput = true
)
)
if not badInput do
(
userVal = userVal as string
i = 1
while i <= userVal.count do
(
for j = 1 to num.count do
(
if userVal[i] == num[j] do
(
if i == j then bulls += 1 else cows += 1
)
)
i += 1
)
numGuesses += 1
format "\nBulls: % Cows: %\n" bulls cows
)
)
- Output:
OK
Rules:
1. Choose only 4 unique digits in any combination (0 can't be used).
2. Only positive integers are allowed.
3. For each digit that is in it's place, you get a bull,
and for each digit that is not in it's place, you get a cow.
4. The game is won when your number matches the number I chose.
Press [esc] to quit the game.
OK
Enter your number: 2468
Bulls: 0 Cows: 2
Enter your number: 2448
The number can only have unique digits.
Enter your number: 1357
Bulls: 0 Cows: 1
MiniScript
secret = range(1,9)
secret.shuffle
secret = secret[:4].join("")
while true
guess = input("Your guess? ").split("")
if guess.len != 4 then
print "Please enter 4 numbers, with no spaces."
continue
end if
bulls = 0
cows = 0
for i in guess.indexes
if secret[i] == guess[i] then
bulls = bulls + 1
else if secret.indexOf(guess[i]) != null then
cows = cows + 1
end if
end for
if bulls == 4 then
print "You got it! Great job!"
break
end if
print "You score " + bulls + " bull" + "s"*(bulls!=1) +
" and " + cows + " cow" + "s"*(cows!=1) + "."
end while
- Output:
Your guess? 2385 You score 0 bulls and 2 cows. Your guess? 2323 You score 0 bulls and 2 cows. Your guess? 2211 You score 2 bulls and 1 cow. ... Your guess? 8542 You score 3 bulls and 0 cows. Your guess? 8642 You got it! Great job!
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.
Nanoquery
import Nanoquery.Util; random = new(Random)
// a function to verify the user's input
def verify_digits(input)
global size
seen = ""
if len(input) != size
return false
else
for char in input
if not char in "0123456789"
return false
else if char in seen
return false
end
seen += char
end
end
return true
end
size = 4
chosen = ""
while len(chosen) < size
digit = random.getInt(8) + 1
if not str(digit) in chosen
chosen += str(digit)
end
end
println "I have chosen a number from 4 unique digits from 1 to 9 arranged in a random order."
println "You need to input a 4 digit, unique digit number as a guess at what I have chosen."
guesses = 1
won = false
while !won
print "\nNext guess [" + str(guesses) + "]: "
guess = input()
if !verify_digits(guess)
println "Problem, try again. You need to enter 4 unique digits from 1 to 9"
else
if guess = chosen
won = true
else
bulls = 0
cows = 0
for i in range(0, size - 1)
if guess[i] = chosen[i]
bulls += 1
else if guess[i] in chosen
cows += 1
end
end
println format(" %d Bulls\n %d Cows", bulls, cows)
guesses += 1
end
end
end
println "\nCongratulations you guess correctly in " + guesses + " attempts"
- 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]: 1234 1 Bulls 2 Cows Next guess [2]: 1324 0 Bulls 3 Cows ... Next guess [10]: 2534 2 Bulls 2 Cows Next guess [11]: 4532 Congratulations you guess correctly in 11 attempts
Nim
import random, strutils, strformat, sequtils
randomize()
const
Digits = "123456789"
DigitSet = {Digits[0]..Digits[^1]}
Size = 4
proc sample(s: string; n: Positive): string =
## Return a random sample of "n" characters extracted from string "s".
var s = s
s.shuffle()
result = s[0..<n]
proc plural(n: int): string =
if n > 1: "s" else: ""
let chosen = Digits.sample(Size)
echo &"I have chosen a number from {Size} unique digits from 1 to 9 arranged in a random order."
echo &"You need to input a {Size} digit, unique digit number as a guess at what I have chosen."
var guesses = 0
while true:
inc guesses
var guess = ""
while true:
stdout.write(&"\nNext guess {guesses}: ")
guess = stdin.readLine().strip()
if guess.len == Size and allCharsInSet(guess, DigitSet) and guess.deduplicate.len == Size:
break
echo &"Problem, try again. You need to enter {Size} unique digits from 1 to 9."
if guess == chosen:
echo &"\nCongratulations! You guessed correctly in {guesses} attempts."
break
var bulls, cows = 0
for i in 0..<Size:
if guess[i] == chosen[i]: inc bulls
elif guess[i] in chosen: inc cows
echo &" {bulls} Bull{plural(bulls)}\n {cows} Cow{plural(cows)}"
- Output:
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: 1234 2 Bulls 0 Cow Next guess 2: 1256 1 Bull 0 Cow Next guess 3: 2378 1 Bull 3 Cows Next guess 4: 7238 Congratulations! You guessed correctly in 4 attempts.
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";
;;
Oforth
: bullsAndCows
| numbers guess digits bulls cows |
ListBuffer new ->numbers
while(numbers size 4 <>) [ 9 rand dup numbers include ifFalse: [ numbers add ] else: [ drop ] ]
while(true) [
"Enter a number of 4 different digits between 1 and 9 : " print
System.Console askln ->digits
digits asInteger isNull digits size 4 <> or ifTrue: [ "Number of four digits needed" println continue ]
digits map(#asDigit) ->guess
guess numbers zipWith(#==) occurrences(true) ->bulls
bulls 4 == ifTrue: [ "You won !" println return ]
guess filter(#[numbers include]) size bulls - ->cows
System.Out "Bulls = " << bulls << ", cows = " << cows << cr
] ;
ooRexx
The solution at Rexx Version 2 is a valid ooRexx program.
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}
PARI/GP
This simple implementation expects guesses in the form [a,b,c,d].
bc()={
my(u,v,bulls,cows);
while(#vecsort(v=vector(4,i,random(9)+1),,8)<4,);
while(bulls<4,
u=input();
if(type(u)!="t_VEC"|#u!=4,next);
bulls=sum(i=1,4,u[i]==v[i]);
cows=sum(i=1,4,sum(j=1,4,i!=j&v[i]==u[j]));
print("You have "bulls" bulls and "cows" cows")
)
};
Pascal
Program BullCow;
{$mode objFPC}
uses Math, SysUtils;
type
TFourDigit = array[1..4] of integer;
Procedure WriteFourDigit(fd: TFourDigit);
{ Write out a TFourDigit with no line break following. }
var
i: integer;
begin
for i := 1 to 4 do
begin
Write(fd[i]);
end;
end;
Function WellFormed(Tentative: TFourDigit): Boolean;
{ Does the TFourDigit avoid repeating digits? }
var
current, check: integer;
begin
Result := True;
for current := 1 to 4 do
begin
for check := current + 1 to 4 do
begin
if Tentative[check] = Tentative[current] then
begin
Result := False;
end;
end;
end;
end;
Function MakeNumber(): TFourDigit;
{ Make a random TFourDigit, keeping trying until it is well-formed. }
var
i: integer;
begin
for i := 1 to 4 do
begin
Result[i] := RandomRange(1, 9);
end;
if not WellFormed(Result) then
begin
Result := MakeNumber();
end;
end;
Function StrToFourDigit(s: string): TFourDigit;
{ Convert an (input) string to a TFourDigit. }
var
i: integer;
begin
for i := 1 to Length(s) do
begin
StrToFourDigit[i] := StrToInt(s[i]);
end;
end;
Function Wins(Num, Guess: TFourDigit): Boolean;
{ Does the guess win? }
var
i: integer;
begin
Result := True;
for i := 1 to 4 do
begin
if Num[i] <> Guess[i] then
begin
Result := False;
Exit;
end;
end;
end;
Function GuessScore(Num, Guess: TFourDigit): string;
{ Represent the score of the current guess as a string. }
var
i, j, bulls, cows: integer;
begin
bulls := 0;
cows := 0;
{ Count the cows and bulls. }
for i := 1 to 4 do
begin
for j := 1 to 4 do
begin
if (Num[i] = Guess[j]) then
begin
{ If the indices are the same, that would be a bull. }
if (i = j) then
begin
bulls := bulls + 1;
end
else
begin
cows := cows + 1;
end;
end;
end;
end;
{ Format the result as a sentence. }
Result := IntToStr(bulls) + ' bulls, ' + IntToStr(cows) + ' cows.';
end;
Function GetGuess(): TFourDigit;
{ Get a well-formed user-supplied TFourDigit guess. }
var
input: string;
begin
WriteLn('Enter a guess:');
ReadLn(input);
{ Must be 4 digits. }
if Length(input) = 4 then
begin
Result := StrToFourDigit(input);
if not WellFormed(Result) then
begin
WriteLn('Four unique digits, please.');
Result := GetGuess();
end;
end
else
begin
WriteLn('Please guess a four-digit number.');
Result := GetGuess();
end;
end;
var
Num, Guess: TFourDigit;
Turns: integer;
begin
{ Initialize the randymnity. }
Randomize();
{ Make the secred number. }
Num := MakeNumber();
WriteLn('I have a secret number. Guess it!');
Turns := 0;
{ Guess until the user gets it. }
While True do
begin
Guess := GetGuess();
{ Count each guess as a turn. }
Turns := Turns + 1;
{ If the user won, tell them and ditch. }
if Wins(Num, Guess) then
begin
WriteLn('You won in ' + IntToStr(Turns) + ' tries.');
Write('The number was ');
WriteFourDigit(Num);
WriteLn('!');
Exit;
end
else { Otherwise, score it and get a new guess. }
begin
WriteLn(GuessScore(Num, Guess));
end;
end;
end.
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}$/;
}
Phix
-- -- demo\rosetta\BullsAndCows.exw -- ============================= -- with javascript_semantics -- (DEV lots of resizing issues) constant N = 4 function mask(integer ch) return power(2,ch-'1') end function function score(string guess, goal) integer bits = 0, bulls = 0, cows = 0, b for i=1 to N do b = goal[i] if guess[i]=b then bulls += 1 else bits += mask(b) end if end for for i=1 to N do b = mask(guess[i]) if and_bits(bits,b)!=0 then cows += 1 bits -= b end if end for return {bulls, cows} end function include pGUI.e Ihandle label, guess, res, dlg string fmt = " Guess %-2d (%s) bulls:%d cows:%d\n", tgt = shuffle("123456789")[1..N] integer attempt = 1 function valuechanged_cb(Ihandle /*guess*/) string g = IupGetAttribute(guess,"VALUE") if length(g)=4 and length(unique(g))=4 then integer {bulls, cows} = score(g,tgt) string title = IupGetAttribute(res,"TITLE") & sprintf(fmt,{attempt,g,bulls,cows}) if bulls=N then title &= "\nWell done!" IupSetInt(guess,"ACTIVE",false) else IupSetAttribute(guess,"VALUE","") end if IupSetStrAttribute(res,"TITLE",title) attempt += 1 IupSetAttribute(dlg,"SIZE",NULL) IupRefresh(dlg) end if return IUP_DEFAULT end function procedure main() IupOpen() label = IupLabel(sprintf("Enter %d digits 1 to 9 without duplication",{N})) guess = IupText("VALUECHANGED_CB", Icallback("valuechanged_cb")) res = IupLabel("") dlg = IupDialog(IupVbox({IupHbox({label,guess},"GAP=10,NORMALIZESIZE=VERTICAL"), IupHbox({res})},"MARGIN=5x5"),`TITLE="Bulls and Cows"`) IupShow(dlg) if platform()!=JS then IupMainLoop() IupClose() end if end procedure main()
- Output:
(as shown in the res label)
Guess 1 (5739) bulls:0 cows:3 Guess 2 (7193) bulls:2 cows:1 Guess 3 (3495) bulls:0 cows:2 Guess 4 (7983) bulls:3 cows:0 Guess 5 (7963) bulls:3 cows:0 Guess 6 (7923) bulls:4 cows:0 Well done!
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);
}
?>
Picat
main =>
Digits = to_array("123456789"),
Size = 4,
random_sample(Size,Size,[],ChosenIndecies),
Chosen = {Digits[I] : I in ChosenIndecies},
printf("I have chosen a number from %d unique digits from 1 to 9 arranged in a random order.\n", Size),
printf("You need to input a %d digit, unique digit number as a guess at what I have chosen.\n", Size),
guess(Chosen,Size,1).
guess(Chosen,Size,NGuess) =>
Input = read_line(),
Guess = Input.to_array(),
if len(Guess) != Size || len(sort_remove_dups(Input)) != Size || (member(D, Input), (D @< '1' || D @> '9')) then
printf("Problem, try again. You need to enter %d unique digits from 1 to 9\n", Size),
guess(Chosen,Size,NGuess)
elseif Guess == Chosen then
printf("\nCongratulations you guessed correctly in %d attempts\n", NGuess)
else
Bulls = sum([cond(Chosen[I] == Guess[I], 1, 0) : I in 1..Size]),
Cows = sum([cond(member(Chosen[I], Input), 1, 0) : I in 1..Size]),
printf("%d Bulls\n%d Cows\n", Bulls, Cows),
guess(Chosen, Size, NGuess+1)
end.
random_sample(_N,0,Chosen0,Chosen) => Chosen = Chosen0.
random_sample(N,I,Chosen0,Chosen) =>
R = random() mod N + 1,
(not member(R, Chosen0) ->
random_sample(N,I-1,[R|Chosen0],Chosen)
;
random_sample(N,I,Chosen0,Chosen)
).
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)" ) ) )
PowerShell
[int]$guesses = $bulls = $cows = 0
[string]$guess = "none"
[string]$digits = ""
while ($digits.Length -lt 4)
{
$character = [char](49..57 | Get-Random)
if ($digits.IndexOf($character) -eq -1) {$digits += $character}
}
Write-Host "`nGuess four digits (1-9) using no digit twice.`n" -ForegroundColor Cyan
while ($bulls -lt 4)
{
do
{
$prompt = "Guesses={0:0#}, Last='{1,4}', Bulls={2}, Cows={3}; Enter your guess" -f $guesses, $guess, $bulls, $cows
$guess = Read-Host $prompt
if ($guess.Length -ne 4) {Write-Host "`nMust be a four-digit number`n" -ForegroundColor Red}
if ($guess -notmatch "[1-9][1-9][1-9][1-9]") {Write-Host "`nMust be numbers 1-9`n" -ForegroundColor Red}
}
until ($guess.Length -eq 4)
$guesses += 1
$bulls = $cows = 0
for ($i = 0; $i -lt 4; $i++)
{
$character = $digits.Substring($i,1)
if ($guess.Substring($i,1) -eq $character)
{
$bulls += 1
}
else
{
if ($guess.IndexOf($character) -ge 0)
{
$cows += 1
}
}
}
}
Write-Host "`nYou won after $($guesses - 1) guesses." -ForegroundColor Cyan
- Output:
Guess four digits (1-9) using no digit twice. Guesses=00, Last='none', Bulls=0, Cows=0; Enter your guess: 1234 Guesses=01, Last='1234', Bulls=0, Cows=3; Enter your guess: 2345 Guesses=02, Last='2345', Bulls=1, Cows=2; Enter your guess: 2346 Guesses=03, Last='2346', Bulls=1, Cows=1; Enter your guess: 2341 Guesses=04, Last='2341', Bulls=1, Cows=2; Enter your guess: 3241 Guesses=05, Last='3241', Bulls=0, Cows=3; Enter your guess: 4321 Guesses=06, Last='4321', Bulls=1, Cows=2; Enter your guess: 5321 Guesses=07, Last='5321', Bulls=2, Cows=2; Enter your guess: 5312 You won after 7 guesses.
Processing
Produces both a console transcript and a GUI interface to the game. Creates a new game each time the guess is correct; tracks number of games won.
IntDict score;
StringList choices;
StringList guess;
StringList secret;
int gamesWon = -1;
void setup() {
choices = new StringList("0", "1", "2", "3", "4", "5", "6", "7", "8", "9");
newGame();
}
void newGame() {
gamesWon++;
choices.shuffle();
secret = new StringList();
for (int i=0; i<4; i++) { // selections
secret.append(choices.get(i));
}
newGuess();
println("\nsecret:", secret, "\n");
}
void newGuess() {
guess = new StringList();
score = null;
}
void draw() {
background(0);
text("Bulls & Cows " + gamesWon, 5, 20);
for (int i=0; i<guess.size(); i++) {
text(guess.get(i), 20*i+10, height/2);
}
if (score!=null) {
text("bulls:" + score.get("bulls") + " cows:" + score.get("cows"), 10, height-20);
}
}
void keyReleased() {
if (score!=null && score.get("bulls")==4) newGame();
if (guess.size()==secret.size()) newGuess();
if (guess.hasValue(str(key))) newGuess();
if (key>=48 && key<=57) guess.append(str(key));
if (guess.size()==secret.size()) {
score = checkScore(secret, guess);
println("guess: ", guess, "\n", score, "wins:", gamesWon);
}
}
IntDict checkScore(StringList secret, StringList guess) {
IntDict result = new IntDict();
result.set("bulls", 0);
result.set("cows", 0);
for (int i=0; i<guess.size(); i++) {
if (guess.get(i).equals(secret.get(i))) {
result.add("bulls", 1);
} else if (secret.hasValue(guess.get(i))) {
result.add("cows", 1);
}
}
return result;
}
Prolog
Works with SWI-Prolog 6.1.8 (for predicate foldl), module lambda, written by Ulrich Neumerkel found there http://www.complang.tuwien.ac.at/ulrich/Prolog-inedit/lambda.pl and module clpfd written by Markus Triska.
:- use_module(library(lambda)).
:- use_module(library(clpfd)).
% Parameters of the server
% length of the guess
proposition(4).
% Numbers of digits
% 0 -> 8
digits(8).
bulls_and_cows_server :-
proposition(LenGuess),
length(Solution, LenGuess),
choose(Solution),
repeat,
write('Your guess : '),
read(Guess),
( study(Solution, Guess, Bulls, Cows)
-> format('Bulls : ~w Cows : ~w~n', [Bulls, Cows]),
Bulls = LenGuess
; digits(Digits), Max is Digits + 1,
format('Guess must be of ~w digits between 1 and ~w~n',
[LenGuess, Max]),
fail).
choose(Solution) :-
digits(Digits),
Max is Digits + 1,
repeat,
maplist(\X^(X is random(Max) + 1), Solution),
all_distinct(Solution),
!.
study(Solution, Guess, Bulls, Cows) :-
proposition(LenGuess),
digits(Digits),
% compute the transformation 1234 => [1,2,3,4]
atom_chars(Guess, Chars),
maplist(\X^Y^(atom_number(X, Y)), Chars, Ms),
% check that the guess is well formed
length(Ms, LenGuess),
maplist(\X^(X > 0, X =< Digits+1), Ms),
% compute the digit in good place
foldl(\X^Y^V0^V1^((X = Y->V1 is V0+1; V1 = V0)),Solution, Ms, 0, Bulls),
% compute the digits in bad place
foldl(\Y1^V2^V3^(foldl(\X2^Z2^Z3^(X2 = Y1 -> Z3 is Z2+1; Z3 = Z2), Ms, 0, TT1),
V3 is V2+ TT1),
Solution, 0, TT),
Cows is TT - Bulls.
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
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
QB64
Const MaxDigit = 4, Min = 1, Max = 9
Dim As String NumberToGuess, NumberToTest, Newdigit, Result
Dim As Integer Counter, Number
Randomize Timer
Do
Counter = Counter + 1
Newdigit = _Trim$(Str$(Int(Rnd * Max) + Min))
If InStr(NumberToGuess, Newdigit) = 0 Then NumberToGuess = NumberToGuess + Newdigit Else Counter = Counter - 1
Loop While Counter < MaxDigit
Print NumberToGuess 'debug output
Do While NumberToGuess <> NumberToTest
Input "Please enter your guess of 4 digits... ", Number
NumberToTest = _Trim$(Str$(Number))
If NumberToGuess <> NumberToTest Then
Result = ""
For Counter = 1 To 4 Step 1
Newdigit = Mid$(NumberToTest, Counter, 1)
If InStr(NumberToGuess, Newdigit) - Counter = 0 Then
Result = Result + " Bull "
ElseIf InStr(NumberToGuess, Newdigit) > 0 Then
Result = Result + " Cow "
End If
Next Counter
Print NumberToTest, Result
Else
Print "You Win!"
End If
Loop
Quackery
transpose
is defined at Matrix transposition#Quackery.
[ size 4 = dup not if
[ say "Must be four digits." cr ] ] is 4chars ( $ --> b )
[ true swap witheach
[ char 1 char 9 1+ within not if
[ say "Must be 1-9 only." cr
not conclude ] ] ] is 1-9 ( $ --> b )
[ 0 9 of
swap witheach
[ 1 unrot char 1 - poke ]
0 swap witheach +
4 = dup not if
[ say "Must all be different." cr ] ] is all-diff ( $ --> b )
[ $ "Guess four digits, 1-9, no duplicates: "
input
dup 4chars not iff drop again
dup 1-9 not iff drop again
dup all-diff not iff drop again ] is guess ( $ --> $ )
[ $ "123456789" shuffle 4 split drop ] is rand$ ( --> $ )
[ 2 pack transpose
[] swap witheach
[ dup unpack != iff
[ nested join ]
else drop ]
dup [] != if
[ transpose unpack ]
4 over size - ] is -bulls ( $ $ --> $ $ n )
[ join sort
0 swap
behead swap witheach
[ tuck = if [ dip 1+ ] ]
drop ] is cows ( $ $ --> n )
[ say "Guess the four numbers." cr cr
say "They are all different and"
say " between 1 and 9 inclusive." cr cr
randomise rand$
[ guess
over -bulls
dup 4 = iff say "Correct." done
dup echo 1 = iff
[ say " bull." cr ]
else
[ say " bulls." cr ]
cows
dup echo 1 = iff
[ say " cow." cr ]
else
[ say " cows." cr ]
again ]
cr drop 2drop ] is play ( --> )
- Output:
Guess the four numbers. They are all different and between 1 and 9 inclusive. Guess four digits, 1-9, no duplicates: 1234 0 bulls. 0 cows. Guess four digits, 1-9, no duplicates: 5678 1 bull. 3 cows. Guess four digits, 1-9, no duplicates: 5786 1 bull. 3 cows. Guess four digits, 1-9, no duplicates: 5867 0 bulls. 4 cows. Guess four digits, 1-9, no duplicates: 7658 2 bulls. 2 cows. Guess four digits, 1-9, no duplicates: 7685 0 bulls. 4 cows. Guess four digits, 1-9, no duplicates: 6758 Correct.
R
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)!"))
Racket
#lang racket
; secret : (listof exact-nonnegative-integer?)
(define secret
(foldr (λ (n result)
(cons n (map (λ (y) (if (>= y n) (add1 y) y))
result)))
'()
(map random '(10 9 8 7))))
; (count-bulls/cows guess) -> (values exact-nonnegative-integer?
; exact-nonnegative-integer?)
; guess : (listof exact-nonnegative-integer?)
(define (count-bulls/cows guess)
(let* ([bulls (map = guess secret)]
[cow-candidates (filter-map (λ (x y) (if (false? x) y #f))
bulls
secret)]
[cows (filter (curryr member cow-candidates) guess)])
(values (length (filter ((curry equal?) #t) bulls))
(length cows))))
; (valid-guess guess-str) -> (or/c (listof exact-nonnegative-integer?) #f)
; guess-str : string?
(define (valid-guess guess-str)
(define (char->digit c)
(- (char->integer c) (char->integer #\0)))
(if (regexp-match-exact? #px"[0-9]{4}" guess-str)
(let ([guess (map char->digit (string->list guess-str))])
(if (andmap (λ (x) (equal? (count ((curry equal?) x) guess) 1))
guess)
guess
#f))
#f))
; Game states
(define win #t)
(define game #f)
; (main-loop state step) -> void?
; state : boolean?
; step : exact-nonnegative-integer?
(define (main-loop state step)
(if (equal? state win)
(printf "You won after ~a guesses." step)
(begin
(let* ([guess-str (read-line)]
[guess (valid-guess guess-str)])
(if (false? guess)
(begin (displayln "Guess should include exactly four different digits")
(main-loop state step))
(let-values ([(bulls cows) (count-bulls/cows guess)])
(if (= bulls 4)
(main-loop win (add1 step))
(begin (printf "Bulls: ~a Cows: ~a\n" bulls cows)
(main-loop state (add1 step))))))))))
(main-loop game 0)
Output:
1234 Bulls: 0 Cows: 1 21345 Guess should include exactly four different digits 2134 Bulls: 1 Cows: 0 2314 Bulls: 0 Cows: 1 5167 Bulls: 1 Cows: 1 5189 Bulls: 1 Cows: 2 0189 Bulls: 1 Cows: 2 8179 Bulls: 1 Cows: 3 7198 You won after 8 guesses.
Raku
(formerly Perl 6)
my $size = 4;
my @secret = pick $size, '1' .. '9';
for 1..* -> $guesses {
my @guess;
loop {
@guess = (prompt("Guess $guesses: ") // exit).comb;
last if @guess == $size and
all(@guess) eq one(@guess) & any('1' .. '9');
say 'Malformed guess; try again.';
}
my ($bulls, $cows) = 0, 0;
for ^$size {
when @guess[$_] eq @secret[$_] { ++$bulls; }
when @guess[$_] eq any @secret { ++$cows; }
}
last if $bulls == $size;
say "$bulls bulls, $cows cows.";
}
say 'A winner is you!';
Red
Red[]
a: "0123456789"
bulls: 0
random/seed now/time
number: copy/part random a 4
while [bulls <> 4] [
bulls: 0
cows: 0
guess: ask "make a guess: "
repeat i 4 [
if (pick guess i) = (pick number i) [bulls: bulls + 1]
]
cows: (length? intersect guess number) - bulls
print ["bulls: " bulls " cows: " cows]
]
print "You won!"
REXX
This game is also known as:
- Pigs and Bulls
- Bulls and Cleots
- Mastermind
- Master Mind
version 1
See version 2 for a better formatted progtam that also runs on ooRexx.
This REXX version of Bulls and Cows doesn't allow repeated digits (in the computer-generated number),
nor the use of the zero digit.
To allow a zero digit, change the 1 on the 2nd REXX statement for the random BIF invocation.
To allow repeated digits in the computer-generated number, delete the 3rd REXX statement if pos(r, ?)···,
and also change the prompt message.
The REXX statement that contains the translate statement can be removed if repeated digits aren't allowed.
/*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. */
Version 2
/*REXX program to play the game of "Bulls & Cows". *******************
* Changes from Version 1:
* ?= -> qq='' (righthandside mandatory and I never use ? as symbol -
* although it is available on all Rexxes)
* implemented singular/plural distinction differently
* change getRand to avoid invalid digit rejection
* check user's input for multiple digits
* add feature MM to ease guessing (MM=Mastermind - a similar game)
* add feature ? to see the solution (for the impatient player)
* program runs as is on ooRexx and on TSO (after changing | to !)
* Made source and output more compact
* formatted source 'my way' 2 July 2012 Walter Pachl
**********************************************************************/
ask='<Bulls & Cows game> Please enter a four-digit guess (or QUIT):'
b.='bulls'; b.1='bull'
c.='cows'; c.1='cow'
qq=getRand()
mm=0
Do Forever
If get_guess()==qq Then leave
Call scorer
Say "You got" bulls b.bulls "and" cows c.cows"."
If mm Then
Say mms
End /*forever*/
Say " *******************************************"
Say " * *"
Say " * Congratulations, you've guessed it !! *"
Say " * *"
Say " *******************************************"
Exit
get_guess: /*get a guess from the guesser. */
do forever
Say ask
Parse Pull guessi
guess=translate(guessi)
bc=verify(guess,987654321)
Select
When guess='?' Then Say qq 'is the correct sequence'
When guess='QUIT' Then Exit
When guess='MM' Then Do
Say 'Mastermind output enabled'
mm=1
End
When guess='' Then Call ser 'no argument specified.'
When words(guess)>1 Then Call ser 'too many arguments specified.'
When verify(0,guess)=0 Then Call ser 'illegal digit: 0'
When bc>0 Then Call ser 'illegal character:' substr(guessi,bc,1)
When length(guess)<4 Then Call ser 'not enough digits'
When length(guess)>4 Then Call ser 'too many digits'
When dups(guess) Then Call ser '4 DIFFERENT digits, please'
Otherwise Do
/********** Say guess ************/
Return guess
End
End
End
getRand:
digits='123456789'
qq=''
Do i=1 To 4
d=random(1,length(digits))
d=substr(digits,d,1)
qq=qq||d
digits=space(translate(digits,' ',d),0)
/************ Say qq digits ************/
End
Return qq
scorer: g=qq
mms='----'
bulls=0
Do j=1 for 4
If substr(guess,j,1)=substr(qq,j,1) Then Do
bulls=bulls+1
guess=overlay(' ',guess,j)
mms=overlay('+',mms,j)
End
End
cows=0
Do j=1 To 4
If pos(substr(guess,j,1),qq)>0 Then Do
cows=cows+1
mms=overlay('.',mms,j)
End
End
Return
dups: Procedure
Parse Arg s
Do i=1 To 3
If pos(substr(s,i,1),substr(s,i+1))>0 Then
Return 1
End
Return 0
ser: Say '*** error ***' arg(1); Return
Ring
# Project : Bulls and cows
secret = ""
while len(secret) != 4
c = char(48 + random(9))
if substr(secret, c) = 0
secret = secret + c
ok
end
see "guess a four-digit number with no digit used twice."
guesses = 0
guess = ""
while true
guess = ""
while len(guess) != 4
see "enter your guess: "
give guess
if len(guess) != 4
see "must be a four-digit number" + nl
ok
end
guesses = guesses + 1
if guess = secret
see "you won after " + guesses + " guesses!"
exit
ok
bulls = 0
cows = 0
for i = 1 to 4
c = secret[i]
if guess[i] = c
bulls = bulls + 1
but substr(guess, c) > 0
cows = cows + 1
ok
next
see "you got " + bulls + " bull(s) and " + cows + " cow(s)." + nl
end
RPL
« CLEAR 0 ""
1 4 START
WHILE RAND 9 * CEIL R→I →STR DUP2 POS REPEAT DROP END +
NEXT
→ count solution
« DO 1 CF
DO "Guess? [CONT]" PROMPT →STR
CASE
DUP SIZE 4 ≠ THEN DROP "Not 4 characters" 1 DISP 0.5 WAIT END
{ 9 } 0 CON
1 4 FOR j
OVER j DUP SUB STR→
IFERR 1 PUT THEN 3 DROPN "Invalid character" 1 DISP 0.5 WAIT END
NEXT
DUP 1 CON DOT 4 ≠ THEN DROP "Repeated digits" 1 DISP 0.5 WAIT END
1 SF
END
UNTIL 1 FS? END
" → " + 0
1 4 FOR j
solution PICK3 j DUP SUB POS
IF DUP THEN IF j == THEN 1 ELSE .1 END END +
NEXT
SWAP OVER + 'count' INCR DROP
UNTIL SWAP 4 == END
count "guess" →TAG
» » 'BU&CO' ST0
Ruby
Inspired by Tcl
def generate_word(len)
[*"1".."9"].shuffle.first(len) # [*"1".."9"].sample(len) ver 1.9+
end
def get_guess(len)
loop do
print "Enter a guess: "
guess = gets.strip
err = case
when guess.match(/[^1-9]/) ; "digits only"
when guess.length != len ; "exactly #{len} digits"
when guess.split("").uniq.length != len; "digits must be unique"
else return guess.split("")
end
puts "the word must be #{len} unique digits between 1 and 9 (#{err}). Try again."
end
end
def score(word, guess)
bulls = cows = 0
guess.each_with_index do |num, idx|
if word[idx] == num
bulls += 1
elsif word.include? num
cows += 1
end
end
[bulls, cows]
end
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
loop do
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."
Inspired by Python
size = 4
secret = [*'1' .. '9'].sample(size)
guess = nil
i=0
loop do
i+=1
loop do
print "Guess #{i}: "
guess = gets.chomp.chars
exit if guess.empty?
break if guess.size == size and
guess.all? { |x| ('1'..'9').include? x } and
guess.uniq.size == size
puts "Problem, try again. You need to enter #{size} unique digits from 1 to 9"
end
if guess == secret
puts "Congratulations you guessed correctly in #{i} attempts"
break
end
bulls = cows = 0
size.times do |j|
if guess[j] == secret[j]
bulls += 1
elsif secret.include? guess[j]
cows += 1
end
end
puts "Bulls: #{bulls}; Cows: #{cows}"
end
Rust
use std::io;
use rand::{Rng,thread_rng};
extern crate rand;
const NUMBER_OF_DIGITS: usize = 4;
static DIGITS: [char; 9] = ['1', '2', '3', '4', '5', '6', '7', '8', '9'];
fn generate_digits() -> Vec<char> {
let mut temp_digits: Vec<_> = (&DIGITS[..]).into();
thread_rng().shuffle(&mut temp_digits);
return temp_digits.iter().take(NUMBER_OF_DIGITS).map(|&a| a).collect();
}
fn parse_guess_string(guess: &str) -> Result<Vec<char>, String> {
let chars: Vec<char> = (&guess).chars().collect();
if !chars.iter().all(|c| DIGITS.contains(c)) {
return Err("only digits, please".to_string());
}
if chars.len() != NUMBER_OF_DIGITS {
return Err(format!("you need to guess with {} digits", NUMBER_OF_DIGITS));
}
let mut uniques: Vec<char> = chars.clone();
uniques.dedup();
if uniques.len() != chars.len() {
return Err("no duplicates, please".to_string());
}
return Ok(chars);
}
fn calculate_score(given_digits: &[char], guessed_digits: &[char]) -> (usize, usize) {
let mut bulls = 0;
let mut cows = 0;
for i in 0..NUMBER_OF_DIGITS {
let pos: Option<usize> = guessed_digits.iter().position(|&a| -> bool {a == given_digits[i]});
match pos {
None => (),
Some(p) if p == i => bulls += 1,
Some(_) => cows += 1
}
}
return (bulls, cows);
}
fn main() {
let reader = io::stdin();
loop {
let given_digits = generate_digits();
println!("I have chosen my {} digits. Please guess what they are", NUMBER_OF_DIGITS);
loop {
let guess_string: String = {
let mut buf = String::new();
reader.read_line(&mut buf).unwrap();
buf.trim().into()
};
let digits_maybe = parse_guess_string(&guess_string);
match digits_maybe {
Err(msg) => {
println!("{}", msg);
continue;
},
Ok(guess_digits) => {
match calculate_score(&given_digits, &guess_digits) {
(NUMBER_OF_DIGITS, _) => {
println!("you win!");
break;
},
(bulls, cows) => println!("bulls: {}, cows: {}", bulls, cows)
}
}
}
}
}
}
Scala
import scala.util.Random
object BullCow {
def main(args: Array[String]): Unit = {
val number=chooseNumber
var guessed=false
var guesses=0
while(!guessed){
Console.print("Guess a 4-digit number with no duplicate digits: ")
val input=Console.readInt
val digits=input.toString.map(_.asDigit).toList
if(input>=1111 && input<=9999 && !hasDups(digits)){
guesses+=1
var bulls, cows=0
for(i <- 0 to 3)
if(number(i)==digits(i))
bulls+=1
else if(number.contains(digits(i)))
cows+=1
if(bulls==4)
guessed=true
else
println("%d Cows and %d Bulls.".format(cows, bulls))
}
}
println("You won after "+guesses+" guesses!");
}
def chooseNumber={
var digits=List[Int]()
while(digits.size<4){
val d=Random.nextInt(9)+1
if (!digits.contains(d))
digits=digits:+d
}
digits
}
def hasDups(input:List[Int])=input.size!=input.distinct.size
}
Scheme
;generate a random non-repeating list of 4 digits, 1-9 inclusive
(define (get-num)
(define (gen lst)
(if (= (length lst) 4) lst
(let ((digit (+ (random 9) 1)))
(if (member digit lst) ;make sure the new digit isn't in the
;list
(gen lst)
(gen (cons digit lst))))))
(string->list (apply string-append (map number->string (gen '())))))
;is g a valid guess (that is, non-repeating, four digits 1-9
;inclusive?)
(define (valid-guess? g)
(let ((g-num (string->number (apply string g))))
;does the same digit appear twice in lst?
(define (repeats? lst)
(cond ((null? lst) #f)
((member (car lst) (cdr lst)) #t)
(else (repeats? (cdr lst)))))
(and g-num
(> g-num 1233)
(< g-num 9877)
(not (repeats? g)))))
;return '(cows bulls) for the given guess
(define (score answer guess)
;total cows + bulls
(define (cows&bulls a g)
(cond ((null? a) 0)
((member (car a) g) (+ 1 (cows&bulls (cdr a) g)))
(else (cows&bulls (cdr a) g))))
;bulls only
(define (bulls a g)
(cond ((null? a) 0)
((equal? (car a) (car g)) (+ 1 (bulls (cdr a) (cdr g))))
(else (bulls (cdr a) (cdr g)))))
(list (- (cows&bulls answer guess) (bulls answer guess)) (bulls answer guess)))
;play the game
(define (bull-cow answer)
;get the user's guess as a list
(define (get-guess)
(let ((e (read)))
(if (number? e)
(string->list (number->string e))
(string->list (symbol->string e)))))
(display "Enter a guess: ")
(let ((guess (get-guess)))
(if (valid-guess? guess)
(let ((bulls (cadr (score answer guess)))
(cows (car (score answer guess))))
(if (= bulls 4)
(display "You win!\n")
(begin
(display bulls)
(display " bulls, ")
(display cows)
(display " cows.\n")
(bull-cow answer))))
(begin
(display "Invalid guess.\n")
(bull-cow answer)))))
(bull-cow (get-num))
Sample game play
Enter a guess: 1234 0 bulls, 1 cows. Enter a guess: 2345 1 bulls, 0 cows. Enter a guess: 2346 1 bulls, 1 cows. Enter a guess: 2367 0 bulls, 1 cows. Enter a guess: 2647 1 bulls, 1 cows. Enter a guess: 2648 2 bulls, 1 cows. Enter a guess: 2468 1 bulls, 2 cows. Enter a guess: 1468 1 bulls, 2 cows. Enter a guess: 2684 0 bulls, 3 cows. Enter a guess: 6248 3 bulls, 0 cows. Enter a guess: 6948 You win!
Scratch
Scratch is a graphical programming language. Follow the link to see an example solution for Bulls and Cows
Scratch - Bulls and Cows
The program "says" the score of the current guess and uses a list to display previous guesses.
Malformed guesses are rejected for the following reasons:
- Guess is longer or shorter than 4 characters
- Guess contains character other than the digits 1 - 9
- Guess contains a digit more than once (i.e. 3484 - this would be rejected because "4" appears in the guess two times)
Since Scratch is an educational language, I've included comments in the code to explain what the program is doing.
Seed7
$ include "seed7_05.s7i";
const proc: main is func
local
const integer: size is 4;
var set of char: digits is {'1' .. '9'};
var string: chosen is " " mult size;
var integer: guesses is 0;
var string: guess is "";
var integer: pos is 0;
var integer: bulls is 0;
var integer: cows is 0;
var boolean: okay is FALSE;
begin
for pos range 1 to 4 do
chosen @:= [pos] rand(digits);
excl(digits, chosen[pos]);
end for;
writeln("I have chosen a number from " <& size <& " unique digits from 1 to 9 arranged in a random order.");
writeln("You need to input a " <& size <& " digit, unique digit number as a guess at what I have chosen");
repeat
incr(guesses);
repeat
write("Next guess [" <& guesses <& "]: ");
readln(guess);
okay := length(guess) = size;
for key pos range guess do
okay := okay and guess[pos] in {'1' .. '9'} and pos(guess[succ(pos) ..], guess[pos]) = 0;
end for;
if not okay then
writeln("Problem, try again. You need to enter " <& size <& " unique digits from 1 to 9");
end if;
until okay;
if guess <> chosen then
bulls := 0;
cows := 0;
for key pos range chosen do
if guess[pos] = chosen[pos] then
incr(bulls);
elsif pos(chosen, guess[pos]) <> 0 then
incr(cows);
end if;
end for;
writeln(" " <& bulls <& " Bulls");
writeln(" " <& cows <& " Cows");
end if;
until guess = chosen;
writeln("Congratulations you guessed correctly in " <& guesses <& " attempts");
end func;
- 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]: 1234 1 Bulls 0 Cows Next guess [2]: 1567 1 Bulls 2 Cows Next guess [3]: 1856 3 Bulls 0 Cows Next guess [4]: 1956 Congratulations you guessed correctly in 4 attempts
SenseTalk
repeat forever
repeat forever
put random(1111,9999) into num
if character 1 of num is not equal to character 2 of num
if character 1 of num is not equal to character 3 of num
if character 1 of num is not equal to character 4 of num
if character 2 of num is not equal to character 3 of num
if character 2 of num is not equal to character 4 of num
if character 3 of num is not equal to character 4 of num
if num does not contain 0
exit repeat
end if
end if
end if
end if
end if
end if
end if
end repeat
set description to "Guess the 4 digit number" & newline & "- zero's excluded" & newline & "- each digit is unique" & newline & newline & "Receive 1 Bull for each digit that equals the corresponding digit in the random number." & newline & newline & "Receive 1 Cow for each digit that appears in the wrong position." & newline
repeat forever
repeat forever
Ask "Guess the number" title "Bulls & Cows" message description
put it into guess
if number of characters in guess is equal to 4
exit repeat
else if guess is ""
Answer "" with "Play" or "Quit" title "Quit Bulls & Cows?"
put it into myAnswer
if myAnswer is "Quit"
exit all
end if
end if
end repeat
set score to {
bulls: {
qty: 0,
values: []
},
cows: {
qty: 0,
values: []
}
}
repeat the number of characters in num times
if character the counter of guess is equal to character the counter of num
add 1 to score.bulls.qty
insert character the counter of guess into score.bulls.values
else
if num contains character the counter of guess
if character the counter of guess is not equal to character the counter of num
if score.bulls.values does not contain character the counter of guess and score.cows.values does not contain character the counter of guess
add 1 to score.cows.qty
insert character the counter of guess into score.cows.values
end if
end if
end if
end if
end repeat
set showScores to "Your score is:" & newline & newline & "Bulls:" && score.bulls.qty & newline & newline & "Cows:" && score.cows.qty
if guess is not equal to num
Answer showScores with "Guess Again" or "Quit" title "Score"
put it into myAnswer
if myAnswer is "Quit"
exit all
end if
else
set winShowScores to showScores & newline & newline & "Your Guess:" && guess & newline & "Random Number:" && num & newline
Answer winShowScores with "Play Again" or "Quit" title "You Win!"
put it into myAnswer
if myAnswer is "Quit"
exit all
end if
exit repeat
end if
end repeat
end repeat
SETL
program bulls_and_cows;
setrandom(0);
print("Bulls and cows");
print("--------------");
print;
secret := make_secret();
loop do
guess := read_guess();
tries +:= 1;
bulls := count_bulls(guess, secret);
cows := count_cows(guess, secret);
print(bulls, "bulls,", cows, "cows.");
if bulls = 4 then
print("You win! Tries:", tries);
exit;
end if;
end loop;
proc make_secret();
digits := [];
loop for i in [1..4] do
loop until not digit in digits do
digit := 1 + random(8);
end loop;
digits with:= digit;
end loop;
return digits;
end proc;
proc read_guess();
loop do
putchar("Guess? ");
flush(stdout);
guess := getline(stdin);
if exists d in guess | not d in "123456789" then
print("invalid input:", d);
elseif #guess /= #{d : d in guess} then
print("no duplicates allowed");
elseif #guess /= 4 then
print("need 4 digits");
else
exit;
end if;
end loop;
return [val d : d in guess];
end proc;
proc count_bulls(guess, secret);
return #[i : i in [1..4] | guess(i) = secret(i)];
end proc;
proc count_cows(guess, secret);
return #[d : d in guess | d in secret] - count_bulls(guess, secret);
end proc;
end program;
- Output:
Bulls and cows -------------- Guess? 1234 0 bulls, 1 cows. Guess? 5678 2 bulls, 1 cows. Guess? 5978 2 bulls, 0 cows. Guess? 5968 1 bulls, 1 cows. Guess? 5976 1 bulls, 1 cows. Guess? 6978 3 bulls, 0 cows. Guess? 6971 2 bulls, 0 cows. Guess? 6918 2 bulls, 0 cows. Guess? 1978 2 bulls, 0 cows. Guess? 6178 3 bulls, 0 cows. Guess? 6278 3 bulls, 0 cows. Guess? 6378 4 bulls, 0 cows. You win! Tries: 12
Shale
#!/usr/local/bin/shale
maths library
file library
string library
n0 var
n1 var
n2 var
n3 var
g0 var
g1 var
g2 var
g3 var
init dup var {
c guess:: var
} =
getNum dup var {
random maths::() 15 >> 9 % 1 +
} =
game dup var {
haveWon dup var false =
ans var
i var
c var
b var
c guess:: 0 =
n0 getNum() =
n1 getNum() =
{ n1 n0 == } {
n1 getNum() =
} while
n2 getNum() =
{ n2 n0 == n2 n1 == or } {
n2 getNum() =
} while
n3 getNum() =
{ n3 n0 == n3 n1 == n3 n2 == or or } {
n3 getNum() =
} while
"New game" println
{ haveWon not } {
"> " print
stdin file:: fgets file::() {
ans swap atoi string::() =
g3 ans 10 % =
g2 ans 10 / 10 % =
g1 ans 100 / 10 % =
g0 ans 1000 / 10 % =
g0 0 > g0 10 < and g1 0 > g1 10 < and g2 0 > g2 10 < and g3 0 > g3 10 < and and and and {
c 0 =
b 0 =
g0 n0 == {
b++
} {
g0 n1 == g0 n2 == g0 n3 == or or { c++ } ifthen
} if
g1 n1 == {
b++
} {
g1 n0 == g1 n2 == g1 n3 == or or { c++ } ifthen
} if
g2 n2 == {
b++
} {
g2 n0 == g2 n1 == g2 n3 == or or { c++ } ifthen
} if
g3 n3 == {
b++
} {
g3 n0 == g3 n1 == g3 n2 == or or { c++ } ifthen
} if
i c guess:: =
i.value guess:: guess:: defined not {
i.value guess:: guess:: var
i.value cow:: guess:: var
i.value bull:: guess:: var
} ifthen
i.value guess:: guess:: ans =
i.value cow:: guess:: c =
i.value bull:: guess:: b =
c guess::++
"Go Guess Cows Bulls" println
i 0 =
{ i c guess:: < } {
i.value bull:: guess:: i.value cow:: guess:: i.value guess:: guess:: i 1 + "%2d %d %4d %5d\n" printf
i++
} while
b 4 == { haveWon true = } ifthen
} {
"Illegal input" println
} if
} {
0 exit
} if
} while
} =
play dup var {
{ true } {
game()
} while
} =
init()
play()
- Output:
New game > 1234 Go Guess Cows Bulls 1 1234 2 0 > 2345 Go Guess Cows Bulls 1 1234 2 0 2 2345 2 0 > 3456 Go Guess Cows Bulls 1 1234 2 0 2 2345 2 0 3 3456 0 2 > 4567 Go Guess Cows Bulls 1 1234 2 0 2 2345 2 0 3 3456 0 2 4 4567 1 0 > 5678 Go Guess Cows Bulls 1 1234 2 0 2 2345 2 0 3 3456 0 2 4 4567 1 0 5 5678 1 1 > 6789 Go Guess Cows Bulls 1 1234 2 0 2 2345 2 0 3 3456 0 2 4 4567 1 0 5 5678 1 1 6 6789 1 0 > 3158 Go Guess Cows Bulls 1 1234 2 0 2 2345 2 0 3 3456 0 2 4 4567 1 0 5 5678 1 1 6 6789 1 0 7 3158 0 4 New game >
Sidef
var size = 4
var num = @(1..9).shuffle.first(size)
for (var guesses = 1; true; guesses++) {
var bulls = 0
var cows = 0
var input =
read("Input: ", String).chars \
.uniq \
.grep(/^[1-9]$/) \
.map{.to_n}
if (input.len != size) {
warn "Invalid input!\n"
guesses--
next
}
if (input == num) {
printf("You did it in %d attempts!\n", guesses)
break
}
for i (^num) {
if (num[i] == input[i]) {
bulls++
}
elsif (num.contains(input[i])) {
cows++
}
}
"Bulls: %d; Cows: %d\n".printf(bulls, cows)
}
- Output:
Input: 2953 Bulls: 1; Cows: 1 Input: 9654 Bulls: 1; Cows: 1 Input: 8924 Bulls: 1; Cows: 3 Input: 2894 You did it in 4 attempts!
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 ].
Smart BASIC
'by rbytes, January 2017
OPTION BASE 1
P(" B U L L S A N D C O W S")!l
P("A secret 4-digit number has been created, with")
P("no repeats and no zeros. You must guess the number.")
P("After each guess, you will be shown how many of your")
P("digits are correct and in the matching location (bulls),")
P("and how many are correct but in a different location (cows).")
p("See how many tries it takes you to get the right answer.")
' generate a 4-digit number with no repeats
guesses = 0
1 WHILE LEN(sec$) <4
c$ =CHR$( INTEG(RND(1) *9) +49)
IF INSTR(sec$, c$)=-1 THEN sec$&=c$
ENDWHILE!l
2 PRINT "Your guess: "
INPUT "FOUR DIGITS": guess$!l
IF guess$="" THEN ' check if entry is null
P("Please enter something!")!l
GOTO 2
ENDIF
P(guess$)!l
IF LEN(guess$)<>4 THEN ' check if entry is exactly 4 characters
P("Please enter exactly 4 digits.")!l
GOTO 2
ENDIF
FOR t=1 TO 4 ' check if all characters are digits 1 - 9
IF INSTR("123456789",MID$(guess$,t,1))=-1 THEN
P("You have entered at least one illegal character")!l
GOTO 2
ENDIF
NEXT t
rep = check(guess$) ' check if any digits are repeated
IF check.chk THEN
P("Please enter a number with no repeated digits.")!l
GOTO 2
ENDIF
guesses+=1
r$=score$(guess$,sec$)
P(r$)!l
IF guess$=sec$ THEN
P("W I N N E R ! ! !")!l
IF guesses>1 THEN gs$="guesses!" ELSE gs$="guess!"
P("You won after "&guesses&" "&gs$)
P("Thanks for playing!")!l
PAUSE 2
P("A G A I N with a new secret number")!l
guesses=0
END IF
GOTO 1
END ' _____________________________________________________________
DEF P(p$) ' function to print a string
PRINT p$
END DEF
DEF L() ' function to print an empty line
PRINT
END DEF
DEF check(i$) ' check=0 if digit is not repeated, else=1
chk=0
FOR i =1 TO 3
FOR j =i +1 TO 4
IF MID$( i$, i, 1)=MID$( i$, j, 1) THEN chk =1
NEXT j
NEXT i
END DEF
DEF score$(a$,b$) ' calculate the numbers of bulls & cows.
bulls=0!cows=0
FOR i = 1 TO 4
c$ = MID$( a$, i, 1)
IF MID$( b$, i, 1)=c$ THEN
bulls+=1
ELSE
IF INSTR( b$, c$) <>-1 AND INSTR( b$, c$) <>i THEN
cows+=1
END IF
END IF
NEXT i
r$ ="Bulls: "&STR$( bulls)& ", "& "Cows: " &STR$( cows)
RETURN r$
END DEF
END
Swift
This is the same as the original solution but takes advantage of Swift 5's richer standard library to clean things up a bit.
func generateRandomNumArray(numDigits: Int = 4) -> [Character]
{
guard (1 ... 9).contains(numDigits) else { fatalError("number out of range") }
return Array("123456789".shuffled()[0 ..< numDigits])
}
func parseGuess(_ guess: String, numDigits: Int = 4) -> String?
{
guard guess.count == numDigits else { return nil }
// Only digits 0 to 9 allowed, no Unicode fractions or numbers from other languages
let guessArray = guess.filter{ $0.isASCII && $0.isWholeNumber }
guard Set(guessArray).count == numDigits else { return nil }
return guessArray
}
func pluralIfNeeded(_ count: Int, _ units: String) -> String
{
return "\(count) " + units + (count == 1 ? "" : "s")
}
var guessAgain = "y"
while guessAgain == "y"
{
let num = generateRandomNumArray()
var bulls = 0
var cows = 0
print("Please enter a 4 digit number with digits between 1-9, no repetitions: ")
if let guessStr = readLine(strippingNewline: true), let guess = parseGuess(guessStr)
{
for (guess, actual) in zip(guess, num)
{
if guess == actual
{
bulls += 1
}
else if num.contains(guess)
{
cows += 1
}
}
print("Actual number: " + num)
print("Your score: \(pluralIfNeeded(bulls, "bull")) and \(pluralIfNeeded(cows, "cow"))\n")
print("Would you like to play again? (y): ")
guessAgain = readLine(strippingNewline: true)?.lowercased() ?? "n"
}
else
{
print("Invalid input")
}
}
import Foundation
func generateRandomNumArray(numDigits: Int = 4) -> [Int] {
guard numDigits > 0 else {
return []
}
let needed = min(9, numDigits)
var nums = Set<Int>()
repeat {
nums.insert(.random(in: 1...9))
} while nums.count != needed
return Array(nums)
}
func parseGuess(_ guess: String) -> [Int]? {
guard guess.count == 4 else {
return nil
}
let guessArray = guess.map(String.init).map(Int.init).compactMap({ $0 })
guard Set(guessArray).count == 4 else {
return nil
}
return guessArray
}
while true {
let num = generateRandomNumArray()
var bulls = 0
var cows = 0
print("Please enter a 4 digit number with digits between 1-9, no repetitions: ")
guard let guessStr = readLine(strippingNewline: true), let guess = parseGuess(guessStr) else {
print("Invalid input")
continue
}
for (guess, actual) in zip(guess, num) {
if guess == actual {
bulls += 1
} else if num.contains(guess) {
cows += 1
}
}
print("Actual number: \(num.map(String.init).joined())")
print("Your score: \(bulls) bulls and \(cows) cows\n")
print("Would you like to play again? (y): ")
guard readLine(strippingNewline: true)!.lowercased() == "y" else {
exit(0)
}
}
- Output:
Please enter a 4 digit number with digits between 1-9, no repetitions: 8496 Actual number: 6475 Your score: 1 bulls and 1 cows Would you like to play again? (y): y Please enter a 4 digit number with digits between 1-9, no repetitions: 5983 Actual number: 7846 Your score: 0 bulls and 1 cows
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
Transd
#lang transd
MainModule: {
contains-duplicates: (λ s String() -> Bool()
(with str String(s) (sort str)
(ret (neq (find-adjacent str) (end str))))
),
play: (λ locals:
syms "0123456789"
len 4
thenum String()
guess String()
(shuffle syms)
(= thenum (substr syms 0 len))
(textout "Your guess: ")
(while (getline guess)
(if (eq guess "q") break)
(if (or (neq (size guess) len)
(neq (find-first-not-of guess syms) -1)
(contains-duplicates guess))
(lout guess " is not valid guess")
(textout "Your guess: ")
continue
)
(with bulls 0 cows 0 pl 0
(for i in Range(len) do
(= pl (index-of thenum (subn guess i)))
(if (eq pl i) (+= bulls 1)
elsif (neq pl -1) (+= cows 1))
)
(lout "bulls: " bulls ", cows: " cows)
(if (eq bulls len)
(lout "Congratulations! You have found out the number!")
(ret null)
else (textout "Your guess: "))
)
)
(lout "You quit the game.")
),
_start: (λ locals: s String()
(lout "Welcome to \"Bulls and cows\"!")
(while true
(while true
(textout "Do you want to play? (yes|no) : ")
(getline s)
(if (not (size s))
(lout "Didn't receive an answer. Exiting.") (exit)
elsif (== (sub (tolower s) 0 1) "n") (lout "Bye!")(exit)
elsif (== (sub (tolower s) 0 1) "y") break
else (lout "(Hint: \"yes\" or \"no\".)"))
)
(play)
(lout "Another game?")
)
)
}
TUSCRIPT
$$ MODE tuscript
SET nr1=RANDOM_NUMBERS (1,9,1)
LOOP
SET nr2=RANDOM_NUMBERS (1,9,1)
IF (nr2!=nr1) EXIT
ENDLOOP
LOOP
SET nr3=RANDOM_NUMBERS (1,9,1)
IF (nr3!=nr1,nr2) EXIT
ENDLOOP
LOOP
SET nr4=RANDOM_NUMBERS (1,9,1)
IF (nr4!=nr1,nr2,nr3) EXIT
ENDLOOP
SET nr=JOIN(nr1,"'",nr2,nr3,nr4), limit=10
LOOP r=1,limit
SET bulls=cows=0
ASK "round {r} insert a number":guessnr=""
SET length=LENGTH(guessnr), checknr=STRINGS (guessnr,":>/:")
LOOP n=nr,y=checknr
IF (length!=4) THEN
PRINT "4-letter digit required"
EXIT
ELSEIF (n==y) THEN
SET bulls=bulls+1
ELSEIF (nr.ct.":{y}:") THEN
SET cows=cows+1
ENDIF
ENDLOOP
PRINT "bulls=",bulls," cows=",cows
IF (bulls==4) THEN
PRINT "BINGO"
EXIT
ELSEIF (r==limit) THEN
PRINT "BETTER NEXT TIME"
EXIT
ENDIF
ENDLOOP
Output:
round 1 insert a number >1234 bulls=1 cows=1 round 2 insert a number >5678 bulls=1 cows=1 round 3 insert a number >1298 bulls=2 cows=0 round 4 insert a number >2379 bulls=0 cows=0 round 5 insert a number >1468 bulls=4 cows=0 BINGO
uBasic/4tH
Local(2) ' Let's use no globals
Proc _Initialize ' Get our secret number
Do ' Repeat until it's guessed
Do
Input "Enter your guess: ";a@ ' Enter your guess
While FUNC(_Invalid(a@)) ' but make sure it's a valid guess
Loop
a@ = FUNC(_Bulls) ' Count the number of bulls
b@ = FUNC(_Cows) ' Count the number of cows
' Now give some feedback
Print : Print "\tThere were ";a@;" bulls and ";b@;" cows." : Print
Until a@ = 4 ' Until the secret is guessed
Loop
Print "You win!" ' Yes, you guessed it
End
_Initialize ' Make a secret
Local (1)
Do
a@ = 1234 + RND(8643) ' Get a valid number
While FUNC(_Invalid(a@)) ' and accept it unless invalid
Loop
For a@ = 0 to 3 ' Now save it at the proper place
@(a@+4) = @(a@)
Next
Return
_Invalid Param(1) ' Check whether a number is valid
Local(2)
' Ok, these can't be right at all
If (a@ < 1234) + (a@ > 9876) Then Return (1)
' Now break 'em up in different digits
For b@ = 3 To 0 Step -1
@(b@) = a@ % 10 ' A digit of zero can't be right
If @(b@) = 0 Then Unloop : Return (1)
a@ = a@ / 10
Next
For b@ = 0 To 2 ' Now compare all digits
For c@ = b@ + 1 To 3 ' The others were already compared
If @(b@) = @(c@) Then Unloop : Unloop : Return (1)
Next ' Wrong, we found similar digits
Next
Return (0) ' All digits are different
_Bulls ' Count the number of valid guesses
Local (2)
b@ = 0 ' Start with zero
For a@ = 0 to 3 ' Increment with each valid guess
If @(a@) = @(a@+4) Then b@ = b@ + 1
Next
Return (b@) ' Return number of valid guesses
_Cows
Local (3) ' Count the number of proper digits
c@ = 0 ' Start with zero
For a@ = 0 To 3 ' All the players guesses
For b@ = 4 To 7 ' All the computers secrets
If (a@+4) = b@ Then Continue ' Skip the bulls
If @(a@) = @(b@) Then c@ = c@ + 1
Next ' Increment with valid digits
Next
Return (c@) ' Return number of valid digits
The addition of strings allows for much simpler code.
Do
s = Str(1234 + RND(8643))
Until FUNC(_Check(s))
Next
Do
Do
g = Ask("Enter your guess: ")
If (Val(g) = Info("nil")) + (Len(g) # 4) Then Continue
Until FUNC(_Check(g))
Loop
b = 0 : c = 0
For i = 0 To 3
For j = 0 to 3
If Peek(s, i) = Peek(g, j) Then
If i = j Then
b = b + 1
Else
c = c + 1
EndIf
EndIf
Next
Next
Print "You scored ";b;" bulls and ";c; " cows.\n"
Until b = 4
Loop
End
_Check
Param (1)
Local (2)
b@ = 0
For c@ = 0 To 3
If Peek(a@, c@) = Ord ("0") Then Unloop : Return (0)
If And(b@, 2^(Peek(a@, c@) - Ord ("0"))) Then Unloop : Return (0)
b@ = b@ + 2^(Peek(a@, c@) - Ord ("0"))
Next
Return (1)
UNIX Shell
#!/bin/bash
rand() {
local min=${1:-0}
local max=${2:-32767}
[ ${min} -gt ${max} ] &&
min=$(( min ^ max )) &&
max=$(( min ^ max )) &&
min=$(( min ^ max ))
echo -n $(( ( $RANDOM % $max ) + $min ))
}
in_arr() {
local quandry="${1}"
shift
local arr=( $@ )
local i=''
for i in ${arr[*]}
do
[ "${quandry}" == "${i}" ] && return 0 && break
done
return 1
}
delete_at() {
local idx="$(( $1 + 1 ))"
shift
local arr=( "sentinel" $@ )
echo -n "${arr[@]:1:$(( idx - 1 ))} ${arr[@]:$((idx + 1)):$(( ${#arr[@]} - idx - 1))}"
}
delete_first() {
local meanie="${1}"
shift
local arr=( $@ )
local i=0
for (( i = 0; i < ${#arr[@]} ; i++ ))
do
[ "${arr[${i}]}" == "${meanie}" ] && arr=( $( delete_at ${i} ${arr[*]} ) )
done
echo -n "${arr[*]}"
}
to_arr() {
local string="${1}"
local arr=()
while [ "${#string}" -gt 0 ]
do
arr=( ${arr[*]} ${string:0:1} )
string="${string:1}"
done
echo -n "${arr[*]}"
}
choose_idx() {
local arr=( $@ )
echo -n "$( rand 0 $(( ${#arr[@]} - 1 )) )"
}
locate_bulls() {
local secret=( $( to_arr "${1}" ) )
local guess=( $( to_arr "${2}" ) )
local hits=()
local i=0
for (( i=0; i<4; i++ ))
do
[ "${secret[${i}]}" -eq "${guess[${i}]}" ] && hits=( ${hits[*]} ${i} )
done
echo -n "${hits[*]}"
}
bulls() {
local secret="${1}"
local guess="${2}"
local bulls=( $( locate_bulls "${secret}" "${guess}" ) )
echo -n "${#bulls[@]}"
}
cows() {
local secret=( $( to_arr "${1}" ) )
local guess=( $( to_arr "${2}" ) )
local bulls=( $( locate_bulls "${1}" "${2}" ) )
local hits=0
local i=''
# Avoid double-counting bulls
for i in ${bulls[*]}
do
secret=( $( delete_at ${i} ${secret[*]} ) )
done
# Process the guess against what's left of the secret
for i in ${guess[*]}
do
in_arr "${i}" ${secret[*]} &&
secret=( $( delete_first "${i}" ${secret[*]} ) ) &&
(( hits++ ))
done
echo -n ${hits}
}
malformed() {
local guess=( $( to_arr "${1}" ) )
local i=''
[ ${#guess[@]} -ne 4 ] &&
return 0
for i in ${guess[*]}
do
if ! in_arr ${i} 1 2 3 4 5 6 7 8 9
then
return 0
break
fi
done
return 1
}
candidates=( 1 2 3 4 5 6 7 8 9 )
secret=''
while [ "${#secret}" -lt 4 ]
do
cidx=$( choose_idx ${candidates[*]} )
secret="${secret}${candidates[${cidx}]}"
candidates=( $(delete_at ${cidx} ${candidates[*]} ) )
done
while read -p "Enter a four-digit guess: " guess
do
malformed "${guess}" && echo "Malformed guess" && continue
[ "${guess}" == "${secret}" ] && echo "You win!" && exit
echo "Score: $( bulls "${secret}" "${guess}" ) Bulls, $( cows "${secret}" "${guess}" ) Cows"
done
VBA
Option Explicit
Sub Main_Bulls_and_cows()
Dim strNumber As String, strInput As String, strMsg As String, strTemp As String
Dim boolEnd As Boolean
Dim lngCpt As Long
Dim i As Byte, bytCow As Byte, bytBull As Byte
Const NUMBER_OF_DIGITS As Byte = 4
Const MAX_LOOPS As Byte = 25 'the max of lines supported by MsgBox
strNumber = Create_Number(NUMBER_OF_DIGITS)
Do
bytBull = 0: bytCow = 0: lngCpt = lngCpt + 1
If lngCpt > MAX_LOOPS Then strMsg = "Max of loops... Sorry you loose!": Exit Do
strInput = AskToUser(NUMBER_OF_DIGITS)
If strInput = "Exit Game" Then strMsg = "User abort": Exit Do
For i = 1 To Len(strNumber)
If Mid(strNumber, i, 1) = Mid(strInput, i, 1) Then
bytBull = bytBull + 1
ElseIf InStr(strNumber, Mid(strInput, i, 1)) > 0 Then
bytCow = bytCow + 1
End If
Next i
If bytBull = Len(strNumber) Then
boolEnd = True: strMsg = "You win in " & lngCpt & " loops!"
Else
strTemp = strTemp & vbCrLf & "With : " & strInput & " ,you have : " & bytBull & " bulls," & bytCow & " cows."
MsgBox strTemp
End If
Loop While Not boolEnd
MsgBox strMsg
End Sub
Function Create_Number(NbDigits As Byte) As String
Dim myColl As New Collection
Dim strTemp As String
Dim bytAlea As Byte
Randomize
Do
bytAlea = Int((Rnd * 9) + 1)
On Error Resume Next
myColl.Add CStr(bytAlea), CStr(bytAlea)
If Err <> 0 Then
On Error GoTo 0
Else
strTemp = strTemp & CStr(bytAlea)
End If
Loop While Len(strTemp) < NbDigits
Create_Number = strTemp
End Function
Function AskToUser(NbDigits As Byte) As String
Dim boolGood As Boolean, strIn As String, i As Byte, NbDiff As Byte
Do While Not boolGood
strIn = InputBox("Enter your number (" & NbDigits & " digits)", "Number")
If StrPtr(strIn) = 0 Then strIn = "Exit Game": Exit Do
If strIn <> "" Then
If Len(strIn) = NbDigits Then
NbDiff = 0
For i = 1 To Len(strIn)
If Len(Replace(strIn, Mid(strIn, i, 1), "")) < NbDigits - 1 Then
NbDiff = 1
Exit For
End If
Next i
If NbDiff = 0 Then boolGood = True
End If
End If
Loop
AskToUser = strIn
End Function
VBScript
VBS functions return variants. I use t to return a single error value or a pair bulls, cows on result
VBS does'nt have a continue so i used the classic do loop inside do loop in the main program
randomize timer
fail=array("Wrong number of chars","Only figures 0 to 9 allowed","Two or more figures are the same")
p=dopuzzle()
wscript.echo "Bulls and Cows. Guess my 4 figure number!"
do
do
wscript.stdout.write vbcrlf & "your move ": s=trim(wscript.stdin.readline)
c=checkinput(s)
if not isarray (c) then wscript.stdout.write fail(c) :exit do
bu=c(0)
wscript.stdout.write "bulls: " & c(0) & " | cows: " & c(1)
loop while 0
loop until bu=4
wscript.stdout.write vbcrlf & "You won! "
function dopuzzle()
dim b(10)
for i=1 to 4
do
r=fix(rnd*10)
loop until b(r)=0
b(r)=1:dopuzzle=dopuzzle+chr(r+48)
next
end function
function checkinput(s)
dim c(10)
bu=0:co=0
if len(s)<>4 then checkinput=0:exit function
for i=1 to 4
b=mid(s,i,1)
if instr("0123456789",b)=0 then checkinput=1 :exit function
if c(asc(b)-48)<>0 then checkinput=2 :exit function
c(asc(b)-48)=1
for j=1 to 4
if asc(b)=asc(mid(p,j,1)) then
if i=j then bu=bu+1 else co=co+1
end if
next
next
checkinput=array(bu,co)
end function
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)
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
V (Vlang)
import rand
import os
fn main() {
valid := ['1','2','3','4','5','6','7','8','9']
mut value := []string{}
mut guess, mut elem := '', ''
mut cows, mut bulls := 0, 0
println('Cows and Bulls')
println('Guess four digit numbers of unique digits in the range 1 to 9.')
println('A correct digit, but not in the correct place is a cow.')
println('A correct digit, and in the correct place is a bull.')
// generate pattern
for value.len < 4 {
elem = rand.string_from_set('123456789', 1)
if value.any(it == elem) == false {
value << elem
}
}
// start game
input: for _ in 0..3 {
guess = os.input('Guess: ').str()
// deal with malformed guesses
if guess.len != 4 {println('Please input a four digit number.') continue input}
for val in guess {
if valid.contains(val.ascii_str()) == false {
{println('Please input a number between 1 to 9.') continue input}
}
if guess.count(val.ascii_str()) > 1 {
{println('Please do not repeat the same digit.') continue input}
}
}
// score guesses
for idx, gval in guess {
match true {
gval.ascii_str() == value[idx] {
bulls++
println('${gval.ascii_str()} was correctly guessed, and in the correct location! ')
}
gval.ascii_str() in value {
cows++
println('${gval.ascii_str()} was correctly quessed, but not in the exact location! ')
}
else {}
}
if bulls == 4 {println('You are correct and have won!!! Congratulations!!!') exit(0)}
}
println('score: bulls: $bulls cows: $cows')
}
println('Only 3 guesses allowed. The correct value was: $value')
println('Sorry, you lost this time, try again.')
}
- Output:
Cows and Bulls Guess four digit numbers of unique digits in the range 1 to 9. A correct digit, but not in the correct place is a cow. A correct digit, and in the correct place is a bull. Guess: 2673 6 was correctly quessed, but not in the exact location! score: bulls: 0 cows: 1 Guess: 1658 6 was correctly quessed, but not in the exact location! 5 was correctly quessed, but not in the exact location! 8 was correctly quessed, but not in the exact location! score: bulls: 0 cows: 4 Guess: 6859 6 was correctly quessed, but not in the exact location! 8 was correctly guessed, and in the correct location! 5 was correctly quessed, but not in the exact location! score: bulls: 1 cows: 6 Only 3 guesses allowed. The correct value was: ['5', '8', '4', '6'] Sorry, you lost this time, try again.
VTL-2
10 I=1
20 J=1
30 :I)='/10*0+%
40 #=:I)=0*30+(0<:I)*70
50 #=:I)=:J)*20
60 J=J+1
70 #=J<I*50
80 I=I+1
90 #=4>I*20
100 ?="BULLS AND COWS"
110 ?="--------------"
120 ?=""
125 T=0
130 T=T+1
140 ?="GUESS? ";
150 G=?
160 #=G<1234+(G>9877)*510
170 I=8
180 G=G/10
190 :I)=%
200 I=I-1
210 #=4<I*180
220 #=:5)*:6)*:7)*:8)=0*510
230 I=6
240 J=5
250 #=:I)=:J)*510
260 J=J+1
270 #=J<I*250
280 I=I+1
290 #=I<9*240
300 B=0
310 C=0
320 I=1
330 B=:I)=:I+4)+B
340 J=1
350 C=(I=J=0)*(:I)=:J+4))+C
360 J=J+1
370 #=4>J*350
380 I=I+1
390 #=4>I*330
400 ?="BULLS: ";
410 ?=B
420 ?=", COWS: ";
430 ?=C
440 ?=""
450 #=B<4*130
460 ?=""
470 ?="YOU GOT IT IN ";
480 ?=T
490 ?=" TRIES!"
500 #=1000
510 ?="BAD GUESS - GUESS NEEDS TO BE 4 UNIQUE DIGITS WITHOUT ZEROES"
520 #=140
- Output:
BULLS AND COWS -------------- GUESS? 1234 BULLS: 0, COWS: 1 GUESS? 5678 BULLS: 0, COWS: 2 GUESS? 1978 BULLS: 1, COWS: 2 GUESS? 2978 BULLS: 1, COWS: 2 GUESS? 3978 BULLS: 1, COWS: 2 GUESS? 4978 BULLS: 1, COWS: 3 GUESS? 7984 BULLS: 1, COWS: 3 GUESS? 8947 BULLS: 4, COWS: 0 YOU GOT IT IN 8 TRIES!
Wren
import "random" for Random
import "./set" for Set
import "./ioutil" for Input
var MAX_GUESSES = 20 // say
var r = Random.new()
var num
// generate a 4 digit random number from 1234 to 9876 with no zeros or repeated digits
while (true) {
num = (1234 + r.int(8643)).toString
if (!num.contains("0") && Set.new(num).count == 4) break
}
System.print("All guesses should have exactly 4 distinct digits excluding zero.")
System.print("Keep guessing until you guess the chosen number (maximum %(MAX_GUESSES) valid guesses).\n")
var guesses = 0
while (true) {
var guess = Input.text("Enter your guess : ")
if (guess == num) {
System.print("You've won with %(guesses+1) valid guesses!")
return
}
var n = Num.fromString(guess)
if (!n) {
System.print("Not a valid number")
} else if (guess.contains("-") || guess.contains("+") || guess.contains(".")) {
System.print("Can't contain a sign or decimal point")
} else if (guess.contains("e") || guess.contains("E")) {
System.print("Can't contain an exponent")
} else if (guess.contains("0")) {
System.print("Can't contain zero")
} else if (guess.count != 4) {
System.print("Must have exactly 4 digits")
} else if (Set.new(guess).count < 4) {
System.print("All digits must be distinct")
} else {
var bulls = 0
var cows = 0
var i = 0
for (c in guess) {
if (num[i] == c) {
bulls = bulls + 1
} else if (num.contains(c)) {
cows = cows + 1
}
i = i + 1
}
System.print("Your score for this guess: Bulls = %(bulls) Cows = %(cows)")
guesses = guesses + 1
if (guesses == MAX_GUESSES) {
System.print("You've now had %(guesses) valid guesses, the maximum allowed")
return
}
}
}
- Output:
Sample game:
All guesses should have exactly 4 distinct digits excluding zero. Keep guessing until you guess the chosen number (maximum 20 valid guesses). Enter your guess : 1234 Your score for this guess: Bulls = 1 Cows = 1 Enter your guess : 1567 Your score for this guess: Bulls = 0 Cows = 1 Enter your guess : 8239 Your score for this guess: Bulls = 2 Cows = 1 Enter your guess : 8294 Your score for this guess: Bulls = 2 Cows = 0 Enter your guess : 8273 Your score for this guess: Bulls = 3 Cows = 0 Enter your guess : 8275 Your score for this guess: Bulls = 2 Cows = 1 Enter your guess : 8263 Your score for this guess: Bulls = 3 Cows = 0 Enter your guess : 8213 Your score for this guess: Bulls = 3 Cows = 0 Enter your guess : 8253 You've won with 9 valid guesses!
XPL0
int Bulls, Cows, Secret(4), Guess(4), Guesses, Used, I, J, Done, Digit, Okay;
[Used:= 0; \generate secret random number using digits
for I:= 0 to 3 do \ 1 to 9 without any repeated digits
[repeat Digit:= Ran(9)+1;
until (Used & 1<<Digit) = 0;
Used:= Used ! 1<<Digit;
Secret(I):= Digit + ^0;
];
Text(0, "Guess the secret number.^m^j");
Text(0, "Guesses must be four different digits, 1 to 9.^m^j");
Guesses:= 0;
loop [Done:= false; \main game loop
repeat Text(0, "Enter your guess: "); \get valid 4-digits from player
OpenI(0); Used:= 0; I:= 0;
loop [Digit:= ChIn(0);
Okay:= Digit>=^1 and Digit<=^9;
Digit:= Digit & $0F; \convert ASCII to binary
if not Okay or Used & 1<<Digit then
[Text(0,
"Please enter four distinct digits, 1 thru 9.^m^j");
quit;
];
Guess(I):= Digit + ^0;
Used:= Used ! 1<<Digit;
I:= I+1;
if I = 4 then [Done:= true; quit];
];
until Done;
Guesses:= Guesses+1;
Bulls:= 0; Cows:= 0;
for I:= 0 to 3 do
for J:= 0 to 3 do
if Guess(I) = Secret(J) then
if I=J then Bulls:= Bulls+1
else Cows:= Cows+1;
Text(0, "Bulls: "); IntOut(0, Bulls);
Text(0, " Cows: "); IntOut(0, Cows);
CrLf(0);
if Bulls = 4 then quit;
];
Text(0, "Congratulations! You won in "); IntOut(0, Guesses);
Text(0, " guesses.^m^j");
]
- Output:
Guess the secret number. Guesses must be four different digits, 1 to 9. Enter your guess: 1234 Bulls: 1 Cows: 1 Enter your guess: 3345 Please enter four distinct digits, 1 thru 9. Enter your guess: 0987 Please enter four distinct digits, 1 thru 9. Enter your guess: 1357 Bulls: 1 Cows: 0 Enter your guess:
zkl
Play one game:
d:=Dictionary(); do{ d[(1).random(10)]=True }while(d.len()<4);
abcd:=d.keys.shuffle();
while(1){
guess:=ask("4 digits: ")-" ,";
if(guess.len()!=4 or guess.unique().len()!=4) continue;
bulls:=abcd.zipWith('==,guess).sum(0);
cows:=guess.split("").enumerate()
.reduce('wrap(s,[(n,c)]){ s + (d.find(c,False) and abcd[n]!=c) },0);
if(bulls==4) { println("You got it!"); break; }
"%d bull%s and %d cow%s".fmt(bulls,s(bulls),cows,s(cows)).println();
}
fcn s(n){ (n!=1) and "s" or "" }
- Output:
4 digits: 4,5,6,7 1 bull and 0 cows 4 digits: 1234 0 bulls and 2 cows 4 digits: 3528 You got it!
- Puzzles
- Games
- Programming Tasks
- 8080 Assembly
- ABC
- Action!
- Ada
- ALGOL 68
- APL
- AppleScript
- Arturo
- AutoHotkey
- AWK
- BASIC
- Applesoft BASIC
- Commodore BASIC
- IS-BASIC
- ZX Spectrum Basic
- Batch File
- BBC BASIC
- BCPL
- Brat
- C
- Ncurses
- C sharp
- C++
- Ceylon
- Clojure
- CLU
- Coco
- Underscore.js
- Common Lisp
- Crystal
- D
- Delphi
- Draco
- E
- EasyLang
- Eiffel
- Elena
- Elixir
- Erlang
- Euphoria
- F Sharp
- FreeBASIC
- Factor
- Fan
- FOCAL
- Forth
- Fortran
- Frink
- FutureBasic
- Pages with broken file links
- Go
- Golo
- Groovy
- Haskell
- Hy
- Icon
- Unicon
- J
- Java
- JavaScript
- Jq
- Julia
- K
- Kotlin
- Lasso
- Liberty BASIC
- Logo
- Lua
- M2000 Interpreter
- Maple
- Mathematica
- Wolfram Language
- MATLAB
- MAXScript
- MiniScript
- MUMPS
- Nanoquery
- Nim
- OCaml
- Oforth
- OoRexx
- Oz
- PARI/GP
- Pascal
- Perl
- Phix
- PHP
- Picat
- PicoLisp
- PowerShell
- Processing
- Prolog
- PureBasic
- Python
- QB64
- Quackery
- R
- Racket
- Raku
- Red
- REXX
- Ring
- RPL
- Ruby
- Rust
- Rand
- Scala
- Scheme
- Scratch
- Seed7
- SenseTalk
- SETL
- Shale
- Sidef
- Smalltalk
- Smart BASIC
- Swift
- Tcl
- Transd
- TUSCRIPT
- UBasic/4tH
- UNIX Shell
- VBA
- VBScript
- Vedit macro language
- Visual Basic .NET
- V (Vlang)
- VTL-2
- Wren
- Wren-set
- Wren-ioutil
- XPL0
- Zkl