Mastermind: Difference between revisions

m
(promoted draft task to a (full) task.)
 
(42 intermediate revisions by 22 users not shown)
Line 1:
[[Category:Puzzles]]
 
{{task|Games}}
 
Create a simple version of the board game:   [https://en.wikipedia.org/wiki/Mastermind_(board_game) Mastermind].
 
It must be possible to:
:*   choose the number of colors will be used in the game (2 - 20)
:*   choose the color code length (4 - 10)
:*   choose the maximum number of guesses the player has (7 - 20)
:*   choose whether or not willcolors may be repeated colors in the code
 
<br>
The (computer program) game should display all the player guesses and the results of that guess.
 
Display (just an idea.):
:::::: {| class="wikitable" border="1"
|-
! Feature !! Graphic Version !! Text Version
Line 37 ⟶ 36:
|}
 
 
A text version example:
A text version example: &nbsp; &nbsp; &nbsp; <big> 1. &nbsp; ADEF &nbsp; - &nbsp; XXO- </big>
1: ADEF - XXO-
<br>Translates to:
<br>the first guess;
<br>the four colors (ADEF);
<br>result:
<br>result: two correct colors and spot, one correct color/wrong spot one color is not in the code.
:::: two correct colors and spot,
:::: one correct color/wrong spot, one color isn't in the code.
 
Happy coding!
Line 53 ⟶ 54:
* &nbsp; [[Guess the number/With Feedback]]
<br><br>
 
=={{header|11l}}==
{{trans|Python}}
 
<syntaxhighlight lang="11l">F encode(correct, guess)
[String] output_arr
 
L(i) 0 .< correct.len
output_arr [+]= I guess[i] == correct[i] {‘X’} E I guess[i] C correct {‘O’} E ‘-’
 
R output_arr
 
F safe_int_input(prompt, min_val, max_val)
L
V user_input_str = input(prompt)
 
X.try
V user_input = Int(user_input_str)
I user_input C min_val .. max_val
R user_input
X.catch ValueError
L.continue
 
F play_game()
print(‘Welcome to Mastermind.’)
print(‘You will need to guess a random code.’)
print(‘For each guess, you will receive a hint.’)
print(‘In this hint, X denotes a correct letter, and O a letter in the original string but in a different position.’)
print()
 
V number_of_letters = safe_int_input(‘Select a number of possible letters for the code (2-20): ’, 2, 20)
V code_length = safe_int_input(‘Select a length for the code (4-10): ’, 4, 10)
 
V letters = ‘ABCDEFGHIJKLMNOPQRST’[0 .< number_of_letters]
V code = ‘’
L 0 .< code_length
code ‘’= random:choice(letters)
[String] guesses
 
L
print()
V guess = input(‘Enter a guess of length #. (#.): ’.format(code_length, letters)).uppercase()
 
I guess.len != code_length | any(guess.map(char -> char !C @letters))
L.continue
E I guess == code
print("\nYour guess "guess‘ was correct!’)
L.break
E
guesses.append(‘#.: #. => #.’.format(guesses.len + 1, Array(guess).join(‘ ’), encode(code, guess).join(‘ ’)))
 
L(i_guess) guesses
print(‘------------------------------------’)
print(i_guess)
print(‘------------------------------------’)
 
play_game()</syntaxhighlight>
 
{{out}}
<pre>
Welcome to Mastermind.
You will need to guess a random code.
For each guess, you will receive a hint.
In this hint, X denotes a correct letter, and O a letter in the original string but in a different position.
 
Select a number of possible letters for the code (2-20): 4
Select a length for the code (4-10): 4
 
Enter a guess of length 4 (ABCD): abcd
------------------------------------
1: A B C D => X X O O
------------------------------------
 
Enter a guess of length 4 (ABCD): abcc
------------------------------------
1: A B C D => X X O O
------------------------------------
2: A B C C => X X O X
------------------------------------
 
Enter a guess of length 4 (ABCD): abdc
 
Your guess ABDC was correct!
</pre>
 
=={{header|Action!}}==
<syntaxhighlight lang="action!">DEFINE MINCOLORS="2"
DEFINE MAXCOLORS="20"
DEFINE MINLENGTH="4"
DEFINE MAXLENGTH="10"
DEFINE MINGUESS="7"
DEFINE MAXGUESS="20"
TYPE Score=[BYTE spot,corr,err]
TYPE Settings=[BYTE colors,length,guesses,repeat]
 
PROC GetSettings(Settings POINTER s)
CHAR ARRAY tmp(10)
 
DO
PrintF("Enter number of colors (%B-%B):",MINCOLORS,MAXCOLORS)
s.colors=InputB()
UNTIL s.colors>=MINCOLORS AND s.colors<=MAXCOLORS
OD
DO
PrintF("Enter length of code (%B-%B):",MINLENGTH,MAXLENGTH)
s.length=InputB()
UNTIL s.length>=MINLENGTH AND s.length<=MAXLENGTH
OD
DO
PrintF("Enter max number of guesses (%B-%B):",MINGUESS,MAXGUESS)
s.guesses=InputB()
UNTIL s.guesses>=MINGUESS AND s.guesses<=MAXGUESS
OD
IF s.colors<s.length THEN
s.repeat=1
ELSE
DO
Print("Allow repeated colors (Y/N):")
InputS(tmp)
IF tmp(0)=1 THEN
IF tmp(1)='y OR tmp(1)='Y THEN
s.repeat=1 EXIT
ELSEIF tmp(1)='n OR tmp(1)='N THEN
s.repeat=0 EXIT
FI
FI
OD
FI
RETURN
 
PROC Generate(CHAR ARRAY code Settings POINTER s)
CHAR ARRAY col(MAXCOLORS)
BYTE i,j,d,tmp,count
 
FOR i=0 TO MAXCOLORS-1
DO
col(i)=i+'A
OD
code(0)=s.length
count=s.colors
FOR i=1 TO s.length
DO
d=Rand(count)
code(i)=col(d)
IF s.repeat=0 THEN
count==-1
col(d)=col(count)
FI
OD
RETURN
 
BYTE FUNC GetCount(CHAR ARRAY s CHAR c)
BYTE i,count
 
count=0
FOR i=1 TO s(0)
DO
IF s(i)=c THEN
count==+1
FI
OD
RETURN (count)
 
PROC CheckScore(CHAR ARRAY code,guess
Settings POINTER s Score POINTER res)
BYTE i,j,codeCount,guessCount
 
res.spot=0
res.corr=0
IF guess(0)#s.length THEN
res.err=1
RETURN
FI
res.err=0
 
FOR i=0 TO s.colors-1
DO
codeCount=GetCount(code,i+'A)
guessCount=GetCount(guess,i+'A)
IF codeCount<guessCount THEN
res.corr==+codeCount
ELSE
res.corr==+guessCount
FI
OD
FOR i=1 TO s.length
DO
IF guess(i)=code(i) THEN
res.spot==+1
res.corr==-1
FI
OD
RETURN
 
PROC ToUpper(CHAR ARRAY s)
BYTE i,c
 
IF s(0)=0 THEN RETURN FI
FOR i=1 TO s(0)
DO
c=s(i)
IF c>='a AND c<='z THEN
s(i)=c-'a+'A
FI
OD
RETURN
 
PROC PrintScore(Score POINTER res Settings POINTER s)
INT i
 
FOR i=1 TO res.spot
DO Put('X) OD
FOR i=1 TO res.corr
DO Put('O) OD
FOR i=1 TO s.length-res.spot-res.corr
DO Put('-) OD
RETURN
 
PROC Main()
CHAR ARRAY code(MAXLENGTH+1),guess(255)
Score res
Settings s
BYTE tries
 
PrintE("Mastermind") PutE()
GetSettings(s) PutE()
Generate(code,s)
tries=s.guesses
PrintF("Enter your guess (%B tries):%E",tries)
DO
InputS(guess) ToUpper(guess)
CheckScore(code,guess,s,res)
Put(28) ;cursor up
PrintF("%S -> ",guess)
IF res.err THEN
Print("Wrong input")
ELSE
PrintScore(res,s)
IF res.spot=s.length THEN
PutE() PutE()
PrintE("You won!")
EXIT
FI
tries==-1
IF tries=0 THEN
PutE() PutE()
PrintE("You lost!")
EXIT
FI
FI
PrintF(", try again (%B tries):%E",tries)
OD
RETURN</syntaxhighlight>
{{out}}
[https://gitlab.com/amarok8bit/action-rosetta-code/-/raw/master/images/Mastermind.png Screenshot from Atari 8-bit computer]
<pre>
Mastermind
 
Enter number of colors (2-20):6
Enter length of code (4-10):5
Enter max number of guesses (7-20):20
Allow repeated colors (Y/N):Y
 
Enter your guess (20 tries):
AAAA -> Wrong input, try again (20 tries):
AAAAA -> -----, try again (19 tries):
BBBBB -> -----, try again (18 tries):
CCCCC -> -----, try again (17 tries):
DDDDD -> XX---, try again (16 tries):
EEEEE -> X----, try again (15 tries):
DDEFF -> XXXXX
 
You won!
</pre>
 
=={{header|Ada}}==
{{works with|Ada|Ada|2012}}
 
<syntaxhighlight lang="ada">with Ada.Text_IO;
with Ada.Numerics.Discrete_Random;
with Ada.Strings.Fixed;
with Ada.Containers.Ordered_Sets;
 
use Ada.Strings.Fixed;
 
procedure MasterMind
is
subtype Color_Number is Positive range 2 .. 20;
subtype Code_Size is Positive range 4 .. 10;
subtype Guesses_Number is Positive range 7 .. 20;
subtype Color is Character range 'A' .. 'T';
 
function Hint(correct, guess : in String) return String
is
Xs : Natural := 0;
Os : Natural := 0;
to_display : String(1 .. correct'Length) := (others => '-');
begin
for I in guess'Range loop
if guess(I) = correct(I) then
Xs := Xs + 1;
to_display(I) := 'X';
end if;
end loop;
for I in guess'Range loop
if to_display(I) = '-' then
for J in correct'Range loop
if J /= I and to_display(J) /= 'X' and correct(J) = guess(I) then
Os := Os + 1;
exit;
end if;
end loop;
end if;
end loop;
return Xs * 'X' & Os * 'O' & (guess'Length - Xs - Os) * '-';
end Hint;
 
generic
type Data is (<>);
function Input(message : in String) return Data;
-- Input will loop until a correct value is given by the user.
-- For each wrong input, the program will prompt the range of expected values.
 
function Input(message : in String) return Data is
begin
loop
Ada.Text_IO.Put(message);
declare
S : constant String := Ada.Text_IO.Get_Line;
begin
return Data'Value(S);
exception
when Constraint_Error =>
Ada.Text_IO.New_Line;
Ada.Text_IO.Put_Line("Invalid input!");
Ada.Text_IO.Put_Line
("Expected values in range:"
& Data'First'Img & " .." & Data'Last'Img);
Ada.Text_IO.New_Line;
end;
end loop;
end;
 
function Input_Color_Number is new Input(Color_Number);
function Input_Code_Size is new Input(Code_Size);
function Input_Guesses_Number is new Input(Guesses_Number);
function Input_Boolean is new Input(Boolean);
 
CN : constant Color_Number := Input_Color_Number("How many colors? ");
GN : constant Guesses_Number := Input_Guesses_Number("How many guesses? ");
CS : constant Code_Size := Input_Code_Size("Size of the code? ");
repeats : Boolean := Input_Boolean("With repeats? ");
-- Not constant: if Color < Code_Size, we will have repetitions anyway.
 
subtype Actual_Colors is Color range Color'First .. Color'Val(Color'Pos(Color'First) + CN - 1);
package Actual_Colors_Sets is new Ada.Containers.Ordered_Sets(Element_Type => Actual_Colors);
 
package Color_Random is new Ada.Numerics.Discrete_Random(Result_Subtype => Actual_Colors);
generator : Color_Random.Generator;
 
function Random return String
is
C : String(1 .. CS);
seen : Actual_Colors_Sets.Set;
begin
for I in C'Range loop
C(I) := Color_Random.Random(generator);
while (not repeats) and seen.Contains(C(I)) loop
C(I) := Color_Random.Random(generator);
end loop;
seen.Include(C(I));
end loop;
return C;
end Random;
 
function Get_Code return String is
begin
loop
Ada.Text_IO.Put("> ");
declare
input : constant String := Ada.Text_IO.Get_Line;
begin
if input'Length /= CS then
raise Constraint_Error;
end if;
for C of input loop
if C not in Actual_Colors then
raise Constraint_Error;
end if;
end loop;
return input;
exception
when Constraint_Error =>
Ada.Text_IO.New_Line;
Ada.Text_IO.Put_Line("Invalid input!");
Ada.Text_IO.New_Line;
end;
end loop;
end Get_Code;
 
found : Boolean := False;
begin
if (not repeats) and (CN < CS) then
Ada.Text_IO.Put_Line("Not enough colors! Using repeats anyway.");
repeats := True;
end if;
 
Color_Random.Reset(generator);
 
declare
answer : constant String := Random;
previous : array(1 .. GN) of String(1 .. CS*2);
begin
for I in 1 .. GN loop
declare
guess : constant String := Get_Code;
begin
if guess = answer then
Ada.Text_IO.Put_Line("You won, congratulations!");
found := True;
else
previous(I) := guess & Hint(answer, guess);
Ada.Text_IO.Put_Line(44 * '-');
for J in 1 .. I loop
Ada.Text_IO.Put_Line
(previous(J)(1 .. CS)
& " => " & previous(J)(CS+1 .. previous(J)'Last));
end loop;
Ada.Text_IO.Put_Line(44 * '-');
Ada.Text_IO.New_Line;
end if;
end;
exit when found;
end loop;
if not found then
Ada.Text_IO.Put_Line("You lost, sorry! The answer was: " & answer);
end if;
end;
end MasterMind;
</syntaxhighlight>
{{out}}
<pre>How many colors? 9
How many guesses? 4
 
Invalid input!
Expected values in range: 7 .. 20
 
How many guesses? 20
Size of the code? 4
With repeats? False
> ABCD
--------------------------------------------
ABCD => XOO-
--------------------------------------------
 
> EFGH
--------------------------------------------
ABCD => XOO-
EFGH => O---
--------------------------------------------
 
> ABCE
--------------------------------------------
ABCD => XOO-
EFGH => O---
ABCE => XOO-
--------------------------------------------
 
> ABCF
--------------------------------------------
ABCD => XOO-
EFGH => O---
ABCE => XOO-
ABCF => XOO-
--------------------------------------------
 
> ABCG
--------------------------------------------
ABCD => XOO-
EFGH => O---
ABCE => XOO-
ABCF => XOO-
ABCG => XXOO
--------------------------------------------
 
> ACBG
You won, congratulations!
</pre>
 
=={{header|APL}}==
{{works with|GNU APL}}
 
<syntaxhighlight lang="apl">#!/usr/local/bin/apl -s -f --
 
⍝ Define the alphabet
A←'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
 
⍝ Make ASCII values upper case
∇n←AscUp c
n←c-32×(c≥97)∧(c≤122)
 
⍝ Does a list have repeated values?
∇r←Rpts l
r←(l⍳l)≢⍳⍴l
 
⍝ Keyboard input using ⎕ and ⍞ doesn't work well using GNU APL in script mode,
⍝ so you kind of have to write your own.
⍝ Read a line of text from the keyboard
∇l←ReadLine up;k;z;data
data←'' ⋄ csr←0 ⍝ Start out with empty string and cursor at 0
 
⍝⍝⍝ Keyboard input
in: k←1⎕fio[41]1 ⍝ Read byte from stdin
handle: →(k>127)/skip ⍝ Unicode is not supported (Wumpus doesn't need it)
→(k∊8 127)/back ⍝ Handle backspace
→(k=10)/done ⍝ Newline = Enter key pressed
→(k<32)/in ⍝ For simplicity, disregard terminal control entirely
 
k←(AscUp⍣up)k ⍝ Make key uppercase if necessary
z←k⎕fio[42]0 ⍝ Echo key to stdout
data←data,k ⍝ Insert key into data
→in ⍝ Go get next key
 
⍝⍝⍝ Skip UTF-8 input (read until byte ≤ 127)
skip: k←1⎕fio[41]1 ⋄ →(k>127)/skip ⋄ →handle
⍝⍝ Backspace
back: →(0=⍴data)/in ⍝ If already at beginning, ignore
z←k⎕fio[42]0 ⍝ Backspace to terminal
data←¯1↓data ⍝ Remove character
→in ⍝ Get next key
⍝⍝ We are done, return the line as text
done: l←⎕UCS data
 
⍝ Read a positive number from the keyboard in the range [min...max]
∇n←min ReadNum max;l;z
in: l←ReadLine 0
z←10⎕fio[42]0
→(~l∧.∊'0123456789')/no
→((min≤n)∧max≥n←⍎l)/0
no: ⍞←'Please enter a number between ',(⍕min),' and ',(⍕max),': '
→in
 
⍝ Ask a numeric question
∇n←q Question lim;min;max
(min max)←lim
⍞←q,' [',(⍕min),'..',(⍕max),']? '
n←min ReadNum max
 
⍝ Read a choice from the keyboard
∇c←Choice cs;ks;k;z
ks←AscUp ⎕UCS ↑¨cs ⍝ User should press first letter of choice
in: →(~(k←AscUp 1⎕fio[41]1)∊ks)/in ⍝ Wait for user to make choice
z←(c←⊃cs[↑ks⍳k])⎕fio[42]0 ⍝ Select and output correspoinding choice
 
⍝ Ask the user for game parameters
∇parms←InitGame;clrs;len;gss;rpts
⎕←'∘∘∘ MASTERMIND ∘∘∘' ⋄ ⎕←''
clrs←'How many colors' Question 2 20
len←'Code length' Question 4 10
gss←'Maximum amount of guesses' Question 7 20
⍞←'Allow repeated colors in code (Y/N)? '
rpts←'Yes'≡Choice 'Yes' 'No'
parms←clrs len gss rpts
 
⍝ Generate a code.
∇c←rpts MakeCode parms;clrs;len
(clrs len)←parms
c←A[(1+rpts)⊃(len?clrs)(?len/clrs)]
 
⍝ Let user make a guess and handle errors
∇g←parms Guess code;clrs;rpts;l;right;in
(clrs rpts num)←parms
guess: ⍞←'Guess ',(¯2↑⍕num),': ' ⋄ g←ReadLine 1 ⍝ Read a guess from the keyboard
⍝ Don't count obvously invalid input against the user
→((⍴code)≢⍴g)/len ⍝ Length is wrong
→(~g∧.∊A[⍳clrs])/inv ⍝ Invalid code in input
→((~rpts)∧Rpts g)/rpt ⍝ No repeats allowed
⍝ Give feedback
right←g=code ⍝ Colors in right position
in←g∊code ⍝ Colors not in right position
fb←(+/right)/'X' ⍝ X = amount of matching ones
fb←fb,(+/in∧~right)/'O' ⍝ O = amount of non-matching ones
fb←fb,(+/~in)/'-' ⍝ - = amount of colors not in code
⍞←' --→ ',fb,⎕UCS 10
→0
len: ⎕←'Invalid length.' ⋄ →guess
inv: ⎕←'Invalid color.' ⋄ →guess
rpt: ⎕←'No repeats allowed.' ⋄ →guess
 
⍝ Play the game
∇ Mastermind;clrs;len;gsmax;rpts;code;gs
⎕rl←(2*32)|×/⎕ts ⍝ initialize random seed
(clrs len gsmax rpts)←InitGame
code←rpts MakeCode clrs len
⎕←2 0⍴''
⎕←'The code consists of: ',A[⍳clrs]
gs←0
loop: gs←gs+1
→(gs>gsmax)/lose
→(code≢(clrs rpts gs)Guess code)/loop
⎕←'○○○ Congratulations! ○○○'
⎕←'You won in ',(⍕gs),' guesses.'
→0
lose: ⎕←'Alas, you are out of guesses.'
⎕←'The code was: ',code
 
Mastermind
)OFF</syntaxhighlight>
 
=={{header|AutoHotkey}}==
<syntaxhighlight lang="autohotkey">w := h := 32, maxRows := 10, numPegs := 8
ww := floor(w/2-2), hh := floor(h/2-2)
grid := [], dx := w*4.5
gosub, Decode
 
Gui, Font, S18, Consolas
loop, 4
{
i := A_Index-1
Gui, add, button, % "x" (Mod(i, 4)?"+0":"30") " y"
. (Mod(i, 4)?"10" : "10") " w" w " h" h " vGoal" A_Index , ?
}
 
Gui, Add, Text, % "section x30 h1 0x1000 w" w*6
loop, % maxRows
{
Gui, Font, S18, consolas
row := maxRows - A_Index + 1
loop 4
{
col := A_Index, i:= col-1
Gui, add, button, % "x" (Mod(i, 4)?"+0":"s") " y" (Mod(i, 4)?"p":"+2")
. " w" w " h" h " vButton" row "_" col " gButton"
}
Gui, Font, S13, wingdings 2
loop 2
{
col := A_Index, i:= col-1
Gui, add, text, % "x" (Mod(i,2)?"+1":"s+" dx) " y" (Mod(i,2)?"p":"p+1")
. " w" ww " h" hh " vKeyPeg" row "_" col, % Chr(167)
}
loop 2
{
col := A_Index+2, i:= col-1
Gui, add, text, % "x" (Mod(i,2)?"+1":"s+" dx) " y" (Mod(i,2)?"p":"+1")
. " w" ww " h" hh " vKeyPeg" row "_" col, % Chr(167)
}
Gui, Add, Text, % "section xs h1 0x1000 w" w*6 " y+4"
}
Gui, Font, S12, consolas
Gui, add, Button, % "xs y+10 gSubmit w" W*2 , Submit
Gui, add, Button, % "x+0 gResetMM w" W*2, Reset
Gui, add, Checkbox, % "x+4 vNoDup", No`nDuplicates
Gui, Font, S18
for i, v in pegs
Gui, add, Radio, % "x" (!Mod(i-1, 4)?"10":"+10") " h" h " w" w+20 " vRadio" A_Index, % v
Gui, show
Row := 1
return
;-----------------------------------------------------------------------
GuiClose:
ExitApp
return
;-----------------------------------------------------------------------
Decode:
Gui, Submit, NoHide
pegs:=[], goal := [], usedPeg :=[]
pool := ["😺","🎃","🧨","⚽","😀","☠","👽","❄","🙉","💗"
,"💥","🖐","🏈","🎱","👁","🗨","🤙","👄","🐶","🐴"
,"🦢","🐍","🐞","💣","🐪","🐘","🐰","🐸","🌴","🏀"]
 
loop, % numPegs
{
Random, rnd, 1, % pool.count()
pegs[A_Index] := pool.RemoveAt(rnd)
}
i := 1
while (goal.count()<4)
{
Random, rnd, 1, % pegs.count()
if (NoDup && usedPeg[pegs[rnd]])
continue
goal[i++] := pegs[rnd]
usedPeg[pegs[rnd]] := true
}
return
;-----------------------------------------------------------------------
Button:
if GameEnd
return
 
Gui, Submit, NoHide
RegExMatch(A_GuiControl, "Button(\d+)_(\d+)", m)
if (m1 <> row)
{
thisPeg := Grid[m1, m2]
for i, v in pegs
if (v=thisPeg)
GuiControl,, Radio%i%, 1
GuiControl,, % "Button" row "_" m2, % thisPeg
Grid[row,m2] := thisPeg
}
else
{
loop, % pegs.count()
if Radio%A_Index%
GuiControl,, % A_GuiControl , % grid[m1, m2] := pegs[A_Index]
}
return
;-----------------------------------------------------------------------
Submit:
if (grid[row].count()<4) || GameEnd
return
 
Gui, submit, NoHide
Ans := [], FIP := [], inGoal := []
CIP := CNP := 0, KeyPeg := 1
 
for i, G in Goal
inGoal[G] := (inGoal[G] ? inGoal[G] : 0) +1 ; save inGoal
loop, 4
Ans[A_Index] := Grid[row, A_Index] ; save Ans
for i, A in Ans
if (goal[A_Index] = A)
CIP++, FIP.push(i), inGoal[A]:=inGoal[A] -1 ; Correct In Place, inGoal--
for i, v in FIP
Ans.RemoveAt(v-i+1) ; remove Correct In Place from Answers
for i, A in Ans
if (inGoal[A] > 0)
CNP++, inGoal[A] := inGoal[A] -1 ; Correct Not in Place
loop % CIP
GuiControl,, % "KeyPeg" row "_" KeyPeg++, % Chr(82) ; "✔"
loop % CNP
GuiControl,, % "KeyPeg" row "_" KeyPeg++, % Chr(83) ; "X"
 
if (CIP=4 || row=maxRows)
{
loop 4
GuiControl,, Goal%A_Index%, % Goal[A_Index]
MsgBox % CIP = 4 ? "You Win" : "You lose"
GameEnd := true
}
Row++
return
;-----------------------------------------------------------------------
LAlt:: ; peak at solution (for troubleshooting purposes only!)
loop 4
GuiControl,, Goal%A_Index%, % Goal[A_Index]
While GetKeyState("Lalt", "P")
continue
loop 4
GuiControl,, Goal%A_Index%, % "?"
return
;-----------------------------------------------------------------------
ResetMM:
Grid :=[], GameEnd:= false
loop, 4
{
Random, rnd, 1, % pegs.count()
goal[A_Index] := pegs[rnd]
GuiControl,, Goal%A_Index%, ?
}
 
loop, % maxRows
{
row := maxRows - A_Index + 1
loop 4
{
col := A_Index
GuiControl,, % "KeyPeg" row "_" col, % Chr(167) ; "O"
GuiControl,, % "Button" row "_" col
}
}
gosub Decode
loop, 8
GuiControl,, Radio%A_Index%, % pegs[A_Index]
return
;-----------------------------------------------------------------------</syntaxhighlight>
 
=={{header|BASIC}}==
==={{header|FreeBASIC}}===
<syntaxhighlight lang="freebasic">'--- Declaration of global variables ---
Dim As String colors(1 To 4) => {"A", "B", "C", "D"}
Dim Shared As Integer nr, ub', numlet=4, lencod=4
Dim Shared As String*4 master, pz
ub = Ubound(colors)
nr = 0
 
'--- SUBroutines and FUNCtions ---
Sub Encabezado
Dim As String dup
Color 11: Print "Welcome to Mastermind"
Print "=====================" + Chr(13) + Chr(10) : Color 15
Print "You will need to guess a random code."
Print "For each guess, you will receive a hint:"
Print "X - denotes a correct letter,"
Print "O - denotes a letter in the original"
Print " string but a different position."
Print "You have 12 attempts."
Print "Duplicates are not allowed." + Chr(10)
Print "Good luck!" + Chr(10) + Chr(10) : Color 7
End Sub
 
Sub showresult(test() As String, place1 As Byte, place2 As Byte, place3 As Byte)
Dim As Integer r, n1, n2, n3
Print Using "##: "; nr;
For r = 1 To Ubound(test)
Print test(r);
Next R
Print " : ";
For n1 = 1 To place1
Print "X"; " ";
Next N1
For n2 = 1 To place2
Print "O"; " ";
Next N2
For n3 = 1 To place3
Print "-"; " ";
Next N3
Print : Print
End Sub
 
Sub Inicio
Dim As Integer mind(ub), rands(ub)
Dim As Integer n, aleat
Dim As Boolean repeat = false
For n = 1 To ub
While true
aleat = (Rnd * (ub-1)) + 1
If rands(aleat) <> 1 Then
mind(n) = aleat
rands(aleat) = 1
Exit While
End If
Wend
Next n
For n = 1 To ub
Mid(master,n,1) = Chr(64 + mind(n))
pz &= Chr(64 + mind(n))
Next n
End Sub
 
 
'--- Main Program ---
Randomize Timer
Cls
Dim As Integer guesses = 12
Encabezado
Inicio
Color 15: Print pz : Color 7
Do
Dim As Integer n, p, d, x, posic
Dim As Integer places(1 To 2), place1, place2, place3
Dim As String*4 testbegin
Dim As String test(ub), mastertemp, tmp
Dim As Boolean flag = True
For p = 1 To Ubound(places)
places(p) = 0
Next p
nr += 1
Input "Your guess (ABCD)? " , testbegin
For d = 1 To Ubound(test)
test(d) = Mid(testbegin,d,1)
Next d
For n = 1 To Ubound(test)
If Ucase(test(n)) <> Mid(master,n,1) Then flag = False
Next n
If flag = True Then
Color 10: Print !"\nWell done! You guess correctly." : Sleep : Exit Do
Else
For x = 1 To Len(master)
If Ucase(test(x)) = Mid(master,x,1) Then places(1) += 1
Next x
mastertemp = master
For p = 1 To Ubound(test)
posic = Instr(mastertemp, Ucase(test(p)))
If posic > 0 Then
tmp = mastertemp
mastertemp = Left(tmp,posic-1) + Mid(tmp, posic+1, Len(tmp)-1)
places(2) += 1
End If
Next p
End If
place1 = places(1)
place2 = places(2) - place1
place3 = Len(master) - (place1 + place2)
showresult(test(), place1, place2, place3)
Loop Until nr = guesses
Color 14: Print "The correct combination was: "; pz
Color 7: Print !"\nEnd of game"
Sleep</syntaxhighlight>
 
=={{header|C++}}==
<langsyntaxhighlight lang="cpp">#include <iostream>
#include <algorithm>
#include <ctime>
Line 203 ⟶ 1,114:
return 0;
}
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 232 ⟶ 1,143:
=={{header|EasyLang}}==
 
[https://easylang.onlinedev/apps/mastermind.html Run it]
 
<syntaxhighlight>
<lang>col[] = [ 922 990 171 229 950 808 ]
col[] = [ 802 990 171 229 950 808 ]
len code[] 4
len guess[] 4
#
subr init_vars
row = 70
.
funcproc draw_rate r black white . .
for j rangerange0 2
for c rangerange0 2
move c * 3.5 + 6771.5 r * 11.5 + 129.64 +- j * 3.5
if black > 0
color 000
circle 1.24
black -= 1
elif white > 0
color 999
circle 1.24
white -= 1
else
color 420310
circle 0.7
.
.
.
.
.
funcproc show_code . .
color 642531
move 2722 092
rect 46 8
for i rangeto 4
move i * 8 + 3320 397
color col[code[i]]
circle 2
.
.
funcproc next_rowdraw_guess . .
for ic rangeto 4
move c * 12 + 8 row * 11.5 + 7.5
guess[i] = -1
color col[guess[c]]
.
circle 3.8
for c range 4
.
move c * 9 + 32 row * 11 + 14
color 900
circle 2
color 420
circle 1.7
.
.
funcproc ratenext_row . .
color 420
test[] = code[]
linewidth 11
for i range 4
move if17 guess[i]row =* test[i]11.5 + 7.5
line 60 row black* 11.5 += 17.5
draw_guess
test[i] = -2
move 73.5 row guess[i]* =11.5 -1+ 7.5
color .310
circle 5.0
for icolor range 4753
move for71.5 jrow range* 411.5 + 5
textsize 7
if guess[i] = test[j]
text "✓"
white += 1
.
test[j] = -2
proc rate . .
guess[i] = -1
move 73.5 row * 11.5 + 7.5
color 531
circle 5.2
c[] = code[]
g[] = guess[]
for i to 4
if c[i] = g[i]
black += 1
c[i] = -1
g[i] = -2
.
.
for i to 4
.
move 64 row * 11for +j 11to 4
if c[i] = g[j]
color 642
white += 1
rect 9 6
c[i] = -1
#
g[j] = -2
call draw_rate row black white
row -= 1 .
if black = 4 .
row = -1.
draw_rate row black white
.
if rowcolor = -1531
linewidth 12
call show_code
move 17 row * 11.5 + 7.5
else
line 60 row * 11.5 + 7.5
call next_row
draw_guess
.
row += 1
if black = 4
row = 8
.
if row = 8
show_code
timer 2
else
next_row
.
.
on timer
func new . .
row = -2
call init_vars
.
for i range 4
proc new . .
code[i] = random 6
init_vars
.
for i to 4
color 642
code[i] = randint 6
move 15 0
rect 70 100.
color 420531
move 2710 010
rect 4670 880
move 35linewidth 210
move 5 95
color 864
line 5 5
text "Mastermind"
line 85 5
color 420
move 25line 1085 95
line 255 9495
move 75color 10310
line 75linewidth 947
for rmove range28 896.5
line for58 c range 496.5
move c * 9 + 32 r * 11 +30 1495
color circle 2864
textsize .4
text "Mastermind"
call draw_rate r 0 0
color 310
.
linewidth 0.5
call next_row
move 10 90
line 10 4
move 67 90
line 67 4
move 80 90
line 80 4
for r range0 8
for c range0 4
move c * 12 + 20 r * 11.5 + 7.5
circle 2
.
draw_rate r 0 0
.
guess[1] = 1
guess[2] = 1
guess[3] = 2
guess[4] = 2
next_row
.
proc do_move . .
#
c = (mouse_x - 15) div 12
func do_move . .
guess[c + 1] = truncguess[c + ((mouse_x1] -mod 27.5)6 /+ 9)1
draw_guess
move c * 9 + 32 row * 11 + 14
guess[c] = (guess[c] + 1) mod 6
color col[guess[c]]
circle 3.2
#
if guess[0] > -1 and guess[1] > -1 and guess[2] > -1 and guess[3] > -1
move 64 row * 11 + 11
color 900
rect 8.6 6
move 64.2 row * 11 + 11.2
color 642
rect 8.2 5.6
color 420
move 64.6 row * 11 + 11.6
text "OK"
.
.
on mouse_down
if row = -12
call new
elif mouse_y > row * 11.5 + 90.5 and mouse_y < row * 11.5 + 1910.5 and row < 8
if mouse_x > 2815 and mouse_x < 63.561
call do_move
elif mouse_x > 6567 and mouse_x < 7780
rate
if guess[0] > -1 and guess[1] > -1 and guess[2] > -1 and guess[3] > -1
call rate
.
.
.
.
new
textsize 5
</syntaxhighlight>
linewidth 0.8
call new</lang>
 
=={{header|Go}}==
 
<langsyntaxhighlight Golang="go">package main
 
import (
Line 569 ⟶ 1,496:
none := m.holes - black - white
return blacks[:black] + whites[:white] + nones[:none], black == m.holes
}</langsyntaxhighlight>
{{out|note=using Knuth's five-guess algorithm}}
<pre>
Line 590 ⟶ 1,517:
You found the code in 5 guesses.
</pre>
 
=={{header|Java}}==
<syntaxhighlight lang="java">
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;
import java.util.concurrent.ThreadLocalRandom;
 
public final class MastermindTask {
 
public static void main(String[] aArgs) {
Mastermind mastermind = new Mastermind(4, 8, 12, false);
mastermind.play();
}
private static final class Mastermind {
public Mastermind(int aCodeLength, int aLetterCount, int aGuessCount, boolean aRepeatLetters) {
if ( aCodeLength < 4 ) {
aCodeLength = 4;
} else if ( aCodeLength > 10 ) {
aCodeLength = 10;
}
if ( aLetterCount < 2 ) {
aLetterCount = 2;
} else if ( aLetterCount > 20 ) {
aLetterCount = 20;
}
if ( aGuessCount < 7 ) {
aGuessCount = 7;
} else if ( aGuessCount > 20 ) {
aGuessCount = 20;
}
if ( ! aRepeatLetters && aLetterCount < aCodeLength ) {
aLetterCount = aCodeLength;
}
codeLength = aCodeLength;
letterCount = aLetterCount;
guessCount = aGuessCount;
repeatLetters = aRepeatLetters;
 
String validLetters = "ABCDEFGHIJKLMNOPQRST";
letters = "";
for ( int i = 0; i < letterCount; i++ ) {
letters += validLetters.charAt(i);
}
}
public void play() {
boolean playerWin = false;
goal = createGoal();
 
while ( guessCount > 0 && ! playerWin ) {
showBoard();
if ( checkUserInput(obtainUserGuess()) ) {
playerWin = true;
reader.close();
}
guessCount--;
}
if ( playerWin ) {
System.out.println(newLine + newLine + "--------------------------------" + newLine +
"Very well done! " + newLine + "You found the code: " + goal +
newLine + "--------------------------------" + newLine + newLine);
} else {
System.out.println(newLine + newLine + "--------------------------------" + newLine +
"I'm sorry, you couldn't make it! " + newLine + "The code was: " + goal +
newLine + "--------------------------------" + newLine + newLine);
}
}
private void showBoard() {
for ( int i = 0; i < guesses.size(); i++ ) {
System.out.print(newLine + "--------------------------------" + newLine);
System.out.print(( i + 1 ) + ": ");
for ( char ch : guesses.get(i) ) {
System.out.print(ch + " ");
}
 
System.out.print(" : ");
for ( char ch : results.get(i) ) {
System.out.print(ch + " ");
}
 
final int errorCount = codeLength - results.get(i).size();
for ( int j = 0; j < errorCount; j++ ) {
System.out.print("- ");
}
}
System.out.print(newLine + newLine);
}
private String obtainUserGuess() {
String result = "";
do {
System.out.print("Enter your guess (" + letters + "): ");
result = reader.nextLine().toUpperCase();
if ( result.length() != codeLength ) {
System.out.println("Please try again, your guess should have " + codeLength + " letters");
}
} while ( result.length() != codeLength );
return result;
}
private boolean checkUserInput(String aUserInput) {
List<Character> userInputCharacters = new ArrayList<Character>();
for ( char ch : aUserInput.toCharArray() ) {
userInputCharacters.add(ch);
}
guesses.add(userInputCharacters);
int xCount = 0;
int oCount = 0;
List<Boolean> fullMatches = new ArrayList<Boolean>(Collections.nCopies(codeLength, false));
List<Boolean> partialMatches = new ArrayList<Boolean>(Collections.nCopies(codeLength, false));
for ( int i = 0; i < codeLength; i++ ) {
if ( aUserInput.charAt(i) == goal.charAt(i) ) {
fullMatches.set(i, true);
partialMatches.set(i, true);
xCount++;
}
}
for ( int i = 0; i < codeLength; i++ ) {
if ( fullMatches.get(i) ) {
continue;
}
for ( int j = 0; j < codeLength; j++ ) {
if ( i == j || partialMatches.get(j) ) {
continue;
}
if ( aUserInput.charAt(i) == goal.charAt(j) ) {
partialMatches.set(j, true);
oCount++;
break;
}
}
}
List<Character> nextResult = new ArrayList<Character>();
for ( int i = 0; i < xCount; i++ ) {
nextResult.add('X');
}
for ( int i = 0; i < oCount; i++ ) {
nextResult.add('O');
}
results.add(nextResult);
 
return xCount == codeLength;
}
private String createGoal() {
String result = "";
String lettersCopy = letters;
 
for ( int i = 0; i < codeLength; i++ ) {
final int index = random.nextInt(lettersCopy.length());
result += lettersCopy.charAt(index);
if ( ! repeatLetters ) {
lettersCopy = lettersCopy.substring(0, index) + lettersCopy.substring(index + 1);
}
}
return result;
}
private int codeLength, letterCount, guessCount;
private String letters, goal;
private boolean repeatLetters;
private Scanner reader = new Scanner(System.in);
private List<List<Character>> guesses = new ArrayList<List<Character>>();
private List<List<Character>> results = new ArrayList<List<Character>>();
private final ThreadLocalRandom random = ThreadLocalRandom.current();
private final String newLine = System.lineSeparator();
}
 
}
</syntaxhighlight>
{{ out }}
<pre>
Enter your guess (ABCDEFGH): abcd
 
--------------------------------
1: A B C D : X O O -
 
Enter your guess (ABCDEFGH): bcde
 
--------------------------------
1: A B C D : X O O -
--------------------------------
2: B C D E : O O O -
 
Enter your guess (ABCDEFGH): fbcd
 
--------------------------------
1: A B C D : X O O -
--------------------------------
2: B C D E : O O O -
--------------------------------
3: F B C D : X O O O
 
Enter your guess (ABCDEFGH): fbdc
 
--------------------------------
1: A B C D : X O O -
--------------------------------
2: B C D E : O O O -
--------------------------------
3: F B C D : X O O O
--------------------------------
4: F B D C : X X O O
 
Enter your guess (ABCDEFGH):
 
// continues ...
</pre>
 
=={{header|Javascript}}==
You can try it [http://paulo-jorente.de/webgames/repos/mastermind/ here].
 
<syntaxhighlight lang="javascript">
class Mastermind {
constructor() {
this.colorsCnt;
this.rptColors;
this.codeLen;
this.guessCnt;
this.guesses;
this.code;
this.selected;
this.game_over;
this.clear = (el) => {
while (el.hasChildNodes()) {
el.removeChild(el.firstChild);
}
};
this.colors = ["🤡", "👹", "👺", "👻", "👽", "👾", "🤖", "🐵", "🐭",
"🐸", "🎃", "🤠", "☠️", "🦄", "🦇", "🛸", "🎅", "👿", "🐲", "🦋"
];
}
 
newGame() {
this.selected = null;
this.guessCnt = parseInt(document.getElementById("gssCnt").value);
this.colorsCnt = parseInt(document.getElementById("clrCnt").value);
this.codeLen = parseInt(document.getElementById("codeLen").value);
if (this.codeLen > this.colorsCnt) {
document.getElementById("rptClr").selectedIndex = 1;
}
this.rptColors = document.getElementById("rptClr").value === "yes";
this.guesses = 0;
this.game_over = false;
const go = document.getElementById("gameover");
go.innerText = "";
go.style.visibility = "hidden";
this.clear(document.getElementById("code"));
this.buildPalette();
this.buildPlayField();
}
 
buildPalette() {
const pal = document.getElementById("palette"),
z = this.colorsCnt / 5,
h = Math.floor(z) != z ? Math.floor(z) + 1 : z;
this.clear(pal);
pal.style.height = `${44 * h + 3 * h}px`;
const clrs = [];
for (let c = 0; c < this.colorsCnt; c++) {
clrs.push(c);
const b = document.createElement("div");
b.className = "bucket";
b.clr = c;
b.innerText = this.colors[c];
b.addEventListener("click", () => {
this.palClick(b);
});
pal.appendChild(b);
}
this.code = [];
while (this.code.length < this.codeLen) {
const r = Math.floor(Math.random() * clrs.length);
this.code.push(clrs[r]);
if (!this.rptColors) {
clrs.splice(r, 1);
}
}
}
 
buildPlayField() {
const brd = document.getElementById("board");
this.clear(brd);
const w = 49 * this.codeLen + 7 * this.codeLen + 5;
brd.active = 0;
brd.style.width = `${w}px`;
document.querySelector(".column").style.width = `${w + 20}px`;
this.addGuessLine(brd);
}
 
addGuessLine(brd) {
const z = document.createElement("div");
z.style.clear = "both";
brd.appendChild(z);
brd.active += 10;
for (let c = 0; c < this.codeLen; c++) {
const d = document.createElement("div");
d.className = "bucket";
d.id = `brd${brd.active+ c}`;
d.clr = -1;
d.addEventListener("click", () => {
this.playClick(d);
})
brd.appendChild(d);
}
}
 
palClick(bucket) {
if (this.game_over) return;
if (null === this.selected) {
bucket.classList.add("selected");
this.selected = bucket;
return;
}
if (this.selected !== bucket) {
this.selected.classList.remove("selected");
bucket.classList.add("selected");
this.selected = bucket;
return;
}
this.selected.classList.remove("selected");
this.selected = null;
}
 
vibrate() {
const brd = document.getElementById("board");
let timerCnt = 0;
const exp = setInterval(() => {
if ((timerCnt++) > 60) {
clearInterval(exp);
brd.style.top = "0px";
brd.style.left = "0px";
}
let x = Math.random() * 4,
y = Math.random() * 4;
if (Math.random() < .5) x = -x;
if (Math.random() < .5) y = -y;
brd.style.top = y + "px";
brd.style.left = x + "px";
}, 10);
}
 
playClick(bucket) {
if (this.game_over) return;
if (this.selected) {
bucket.innerText = this.selected.innerText;
bucket.clr = this.selected.clr;
} else {
this.vibrate();
}
}
 
check() {
if (this.game_over) return;
let code = [];
const brd = document.getElementById("board");
for (let b = 0; b < this.codeLen; b++) {
const h = document.getElementById(`brd${brd.active + b}`).clr;
if (h < 0) {
this.vibrate();
return;
}
code.push(h);
}
this.guesses++;
if (this.compareCode(code)) {
this.gameOver(true);
return;
}
if (this.guesses >= this.guessCnt) {
this.gameOver(false);
return;
}
this.addGuessLine(brd);
}
 
compareCode(code) {
let black = 0,
white = 0,
b_match = new Array(this.codeLen).fill(false),
w_match = new Array(this.codeLen).fill(false);
for (let i = 0; i < this.codeLen; i++) {
if (code[i] === this.code[i]) {
b_match[i] = true;
w_match[i] = true;
black++;
}
}
for (let i = 0; i < this.codeLen; i++) {
if (b_match[i]) continue;
for (let j = 0; j < this.codeLen; j++) {
if (i == j || w_match[j]) continue;
if (code[i] === this.code[j]) {
w_match[j] = true;
white++;
break;
}
}
}
const brd = document.getElementById("board");
let d;
for (let i = 0; i < black; i++) {
d = document.createElement("div");
d.className = "pin";
d.style.backgroundColor = "#a00";
brd.appendChild(d);
}
for (let i = 0; i < white; i++) {
d = document.createElement("div");
d.className = "pin";
d.style.backgroundColor = "#eee";
brd.appendChild(d);
}
return (black == this.codeLen);
}
 
gameOver(win) {
if (this.game_over) return;
this.game_over = true;
const cd = document.getElementById("code");
for (let c = 0; c < this.codeLen; c++) {
const d = document.createElement("div");
d.className = "bucket";
d.innerText = this.colors[this.code[c]];
cd.appendChild(d);
}
const go = document.getElementById("gameover");
go.style.visibility = "visible";
go.innerText = win ? "GREAT!" : "YOU FAILED!";
const i = setInterval(() => {
go.style.visibility = "hidden";
clearInterval(i);
}, 3000);
}
}
const mm = new Mastermind();
document.getElementById("newGame").addEventListener("click", () => {
mm.newGame()
});
document.getElementById("giveUp").addEventListener("click", () => {
mm.gameOver();
});
document.getElementById("check").addEventListener("click", () => {
mm.check()
});
</syntaxhighlight>
 
To test you'll need a HTML file
<pre>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="./css/style.css" type="text/css">
<title>Mastermind</title>
</head>
<body>
<div id="gameover"></div>
<div class="column">
<div id="board" style="position: relative"></div>
<div style="clear: both"> </div>
<button id="check" style="margin-top:20px">Check!</button>
<button id="giveUp">Give up!</button>
<div id="code" style="margin-top: 40px"></div>
</div>
<div class="columnS">
<div id="ctrls">
<label for="clrCnt">Colors count:</label>
<input type="number" id="clrCnt" max="20" min="2" value="6"></input>
<br />
<label for="codeLen">Code length:</label>
<input type="number" id="codeLen" max="10" min="4" value="4"></input>
<br />
<label for="gssCnt">Guesses count:</label>
<input type="number" id="gssCnt" max="20" min="7" value="12"></input>
<br />
<label for="rptClr">Repeat colors:</label>
<select id="rptClr">
<option value="no">No</option>
<option value="yes">Yes</option>
</select>
<button id="newGame" style="width: 100%">New game</button>
</div>
<div id="palette"></div>
</div>
<script src="./src/index.js" type="module"></script>
</body>
</html>
</pre>
 
And a CSS file
<pre>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
user-select: none;
}
body {
background-color: #222;
text-align: left
}
button {
width: 101px;
height: 26px;
background-color: #444;
color: #ddd;
border: 1px solid #333;
border-radius: 4px;
}
input,
select {
float: right;
width: 60px;
height: 24px;
margin-top: 6px;
font-size: 20px;
}
#palette {
margin-top: 40px;
width: 233px;
border-radius: 5px;
border: 1px solid #fff;
}
#ctrls {
border-radius: 5px;
border: 1px solid #fff;
padding: 10px;
font-size: 20px;
width: 233px;
line-height: 36px;
color: #fff;
}
#gameover {
position: absolute;
top: 90px;
left: 0;
font-size: 100px;
text-align: center;
color: rgb(248, 143, 4);
background: rgba(34, 34, 34, .8);
padding: 10px;
z-index: 999;
}
.column,
.columnS {
float: left;
width: 249px;
margin: 30px;
}
.columnS {
width: 300px;
margin-left: 0;
}
.bucket {
float: left;
width: 42px;
height: 42px;
line-height: 40px;
font-size: 26px;
border: 2px solid #fff;
border-radius: 3px;
margin: 2px;
cursor: pointer;
}
.selected {
border: 2px solid #d00;
}
.pin {
float: left;
width: 14px;
height: 14px;
border-radius: 50%;
margin: 2px;
}
</pre>
 
=={{header|Julia}}==
GUI version, uses the Gtk toolkit.
<syntaxhighlight lang="julia">using Gtk, Colors, Cairo, Graphics
 
struct Guess
code::Vector{Color}
guess::Vector{Color}
hint::Vector{Color}
end
 
function Guess(code, guess)
len = length(code)
hints = fill(colorant"gray", len) # gray default
for (i, g) in enumerate(guess), (j, c) in enumerate(code)
if g == c
if i == j
hints[i] = colorant"black"
elseif hints[i] != colorant"black"
hints[i] = colorant"white"
end
end
end
g = Guess([c for c in code], [c for c in guess], [c for c in hints])
end
 
tovec(guess) = [x for x in [guess.code; guess.guess; guess.hint]]
 
function mastermindapp()
allu(s) = length(unique(s)) == length(s)
ccode(c, n, rok) = while true a = rand(c, n); if rok || allu(a) return a end end
 
numcolors, codelength, maxguesses, allowrep, gameover = 10, 4, 10, false, false
colors = distinguishable_colors(numcolors)
code = ccode(colors, numcolors, allowrep)
guesshistory = Vector{Guess}()
win = GtkWindow("Mastermind Game", 900, 750) |> (GtkFrame() |> (box = GtkBox(:v)))
settingsbox = GtkBox(:h)
playtoolbar = GtkToolbar()
 
setcolors = GtkScale(false, 4:20)
set_gtk_property!(setcolors, :hexpand, true)
adj = GtkAdjustment(setcolors)
set_gtk_property!(adj, :value, 10)
clabel = GtkLabel("Number of Colors")
 
setcodelength = GtkScale(false, 4:10)
set_gtk_property!(setcodelength, :hexpand, true)
adj = GtkAdjustment(setcodelength)
set_gtk_property!(adj, :value, 4)
slabel = GtkLabel("Code Length")
 
setnumguesses = GtkScale(false, 4:40)
set_gtk_property!(setnumguesses, :hexpand, true)
adj = GtkAdjustment(setnumguesses)
set_gtk_property!(adj, :value, 10)
nlabel = GtkLabel("Max Guesses")
 
allowrepeatcolor = GtkScale(false, 0:1)
set_gtk_property!(allowrepeatcolor, :hexpand, true)
rlabel = GtkLabel("Allow Repeated Colors (0 = No)")
 
newgame = GtkToolButton("New Game")
set_gtk_property!(newgame, :label, "New Game")
set_gtk_property!(newgame, :is_important, true)
 
tryguess = GtkToolButton("Submit Current Guess")
set_gtk_property!(tryguess, :label, "Submit Current Guess")
set_gtk_property!(tryguess, :is_important, true)
 
eraselast = GtkToolButton("Erase Last (Unsubmitted) Pick")
set_gtk_property!(eraselast, :label, "Erase Last (Unsubmitted) Pick")
set_gtk_property!(eraselast, :is_important, true)
 
map(w->push!(settingsbox, w),[clabel, setcolors, slabel, setcodelength,
nlabel, setnumguesses, rlabel, allowrepeatcolor])
map(w->push!(playtoolbar, w),[newgame, tryguess, eraselast])
scrwin = GtkScrolledWindow()
can = GtkCanvas()
set_gtk_property!(can, :expand, true)
map(w -> push!(box, w),[settingsbox, playtoolbar, scrwin])
push!(scrwin, can)
 
currentguess = RGB[]
guessesused = 0
colorpositions = Point[]
function newgame!(w)
empty!(guesshistory)
numcolors = Int(GAccessor.value(setcolors))
codelength = Int(GAccessor.value(setcodelength))
maxguesses = Int(GAccessor.value(setnumguesses))
allowrep = Int(GAccessor.value(allowrepeatcolor))
colors = distinguishable_colors(numcolors)
code = ccode(colors, codelength, allowrep == 1)
empty!(currentguess)
currentneeded = codelength
guessesused = 0
gameover = false
draw(can)
end
signal_connect(newgame!, newgame, :clicked)
function saywon!()
warn_dialog("You have WON the game!", win)
gameover = true
end
 
function outofguesses!()
warn_dialog("You have Run out of moves! Game over.", win)
gameover = true
end
can.mouse.button1press = @guarded (widget, event) -> begin
if !gameover && (i = findfirst(p ->
sqrt((p.x - event.x)^2 + (p.y - event.y)^2) < 20,
colorpositions)) != nothing
if length(currentguess) < codelength
if allowrep == 0 && !allu(currentguess)
warn_dialog("Please erase the duplicate color.", win)
else
push!(currentguess, colors[i])
draw(can)
end
else
warn_dialog("You need to submit this guess if ready.", win)
end
end
end
@guarded draw(can) do widget
ctx = Gtk.getgc(can)
select_font_face(ctx, "Courier", Cairo.FONT_SLANT_NORMAL, Cairo.FONT_WEIGHT_BOLD)
fontpointsize = 12
set_font_size(ctx, fontpointsize)
workcolor = colorant"black"
set_source(ctx, workcolor)
move_to(ctx, 0, fontpointsize)
show_text(ctx, "Color options: " * "-"^70)
stroke(ctx)
empty!(colorpositions)
for i in 1:numcolors
set_source(ctx, colors[i])
circle(ctx, i * 40, 40, 20)
push!(colorpositions, Point(i * 40, 40))
fill(ctx)
end
set_gtk_property!(can, :expand, false) # kludge for good text overwriting
move_to(ctx, 0, 80)
set_source(ctx, workcolor)
show_text(ctx, string(maxguesses - guessesused, pad = 2) * " moves remaining.")
stroke(ctx)
set_gtk_property!(can, :expand, true)
for i in 1:codelength
set_source(ctx, i > length(currentguess) ? colorant"lightgray" : currentguess[i])
circle(ctx, i * 40, 110, 20)
fill(ctx)
end
if length(guesshistory) > 0
move_to(ctx, 0, 155)
set_source(ctx, workcolor)
show_text(ctx, "Past Guesses: " * "-"^70)
for (i, g) in enumerate(guesshistory), (j, c) in enumerate(tovec(g)[codelength+1:end])
x = j * 40 + (j > codelength ? 20 : 0)
y = 150 + 40 * i
set_source(ctx, c)
circle(ctx, x, y, 20)
fill(ctx)
end
end
Gtk.showall(win)
end
 
function submitguess!(w)
if length(currentguess) == length(code)
g = Guess(code, currentguess)
push!(guesshistory, g)
empty!(currentguess)
guessesused += 1
draw(can)
if all(i -> g.code[i] == g.guess[i], 1:length(code))
saywon!()
elseif guessesused > maxguesses
outofguesses!()
end
end
end
signal_connect(submitguess!, tryguess, :clicked)
 
function undolast!(w)
if length(currentguess) > 0
pop!(currentguess)
draw(can)
end
end
signal_connect(undolast!, eraselast, :clicked)
 
newgame!(win)
Gtk.showall(win)
condition = Condition()
endit(w) = notify(condition)
signal_connect(endit, win, :destroy)
showall(win)
wait(condition)
end
 
mastermindapp()
</syntaxhighlight>
 
=={{header|Kotlin}}==
{{trans|C++}}
<langsyntaxhighlight lang="scala">// version 1.2.51
 
import java.util.Random
Line 710 ⟶ 2,444:
val m = Mastermind(4, 8, 12, false)
m.play()
}</langsyntaxhighlight>
 
Sample input/output (showing last 2 guesses only):
Line 750 ⟶ 2,484:
=={{header|Lua}}==
Based on C++
<langsyntaxhighlight lang="lua">
math.randomseed( os.time() )
local black, white, none, code = "X", "O", "-"
Line 829 ⟶ 2,563:
if arg[4] ~= nil and arg[4] == "true" or arg[4] == "false" then rept = ( arg[4] == "true" ) end
play()
</syntaxhighlight>
</lang>
{{out}}
<pre>
Line 853 ⟶ 2,587:
Play again( Y/N )?
</pre>
 
=={{header|Nim}}==
{{trans|Python}}
<syntaxhighlight lang="nim">import random, sequtils, strformat, strutils
 
proc encode(correct, guess: string): string =
result.setlen(correct.len)
for i in 0..correct.high:
result[i] = if correct[i] == guess[i]: 'X' else: (if guess[i] in correct: 'O' else: '-')
result.join(" ")
 
proc safeIntInput(prompt: string; minVal, maxVal: Positive): int =
while true:
stdout.write prompt
let userInput = stdin.readLine()
result = try: parseInt(userInput)
except ValueError: continue
if result in minVal..maxVal:
return
 
 
proc playGame() =
 
echo "You will need to guess a random code."
echo "For each guess, you will receive a hint."
echo "In this hint, X denotes a correct letter, " &
"and O a letter in the original string but in a different position."
echo ""
 
let numLetters = safeIntInput("Select a number of possible letters for the code (2-20): ", 2, 20)
let codeLength = safeIntInput("Select a length for the code (4-10): ", 4, 10)
let letters = "ABCDEFGHIJKLMNOPQRST"[0..<numLetters]
let code = newSeqWith(codeLength, letters.sample()).join()
var guesses: seq[string]
 
while true:
echo ""
stdout.write &"Enter a guess of length {codeLength} ({letters}): "
let guess = stdin.readLine().toUpperAscii().strip()
if guess.len != codeLength or guess.anyIt(it notin letters):
continue
elif guess == code:
echo &"\nYour guess {guess} was correct!"
break
else:
guesses.add &"{guesses.len + 1}: {guess.join(\" \")} => {encode(code, guess)}"
for guess in guesses:
echo "------------------------------------"
echo guess
echo "------------------------------------"
 
 
randomize()
playGame()</syntaxhighlight>
 
{{out}}
<pre>You will need to guess a random code.
For each guess, you will receive a hint.
In this hint, X denotes a correct letter, and O a letter in the original string but in a different position.
 
Select a number of possible letters for the code (2-20): 4
Select a length for the code (4-10): 4
 
Enter a guess of length 4 (ABCD): ABCD
------------------------------------
1: A B C D => - O - X
------------------------------------
 
Enter a guess of length 4 (ABCD): BDBD
------------------------------------
1: A B C D => - O - X
------------------------------------
2: B D B D => X X O X
------------------------------------
 
Enter a guess of length 4 (ABCD): BDDD
 
Your guess BDDD was correct!</pre>
 
=={{header|Perl}}==
{{trans|Perl 6Raku}}
<langsyntaxhighlight lang="perl">use List::Util qw(any);
 
print 'Enter pool size, puzzle size, attempts allowed: ';
Line 907 ⟶ 2,719:
 
sub lose { print 'Too bad, you ran out of guesses. The solution was: ' . join(' ',@puzzle) . "\n"; exit }
</syntaxhighlight>
</lang>
Sample output, omitting redundant instructions.
{{out}}
Line 926 ⟶ 2,738:
Your guess?: b d a c
You win! The correct answer is: B D A C</pre>
 
=={{header|Perl 6}}==
{{works with|Rakudo|2017.01}}
By default, plays classic Mastermind using letters in place of colors. ( 4 chosen from 6, no repeats, 10 guess limit. ) Pass in parameters to modify the game. Enter a string of --length (default 4) letters with or without spaces. Guesses accept lower or upper case.
<lang perl6>sub MAIN (
Int :$colors where 1 < * < 21 = 6, Int :$length where 3 < * < 11 = 4,
Int :$guesses where 7 < * < 21 = 10, Bool :$repeat = False
) {
my @valid = ('A' .. 'T')[^$colors];
my $puzzle = $repeat ?? @valid.roll($length) !! @valid.pick($length);
my @guesses;
 
my $black = '●';
my $white = '○';
 
loop {
clearscr();
say header();
printf " %{$length * 2}s :: %s\n", @guesses[$_][0], @guesses[$_][1] for ^@guesses;
say '';
lose() if @guesses == $guesses;
my $guess = get-guess();
next unless $guess.&is-valid;
my $score = score($puzzle, $guess);
win() if $score eq ($black xx $length).join: ' ';
@guesses.push: [$guess, $score];
}
 
sub header {
my $num = $guesses - @guesses;
qq:to/END/;
Valid letter, but wrong position: ○ - Correct letter and position: ●
Guess the {$length} element sequence containing the letters {@valid}
Repeats are {$repeat ?? '' !! 'not '}allowed. You have $num guess{ $num == 1 ?? '' !! 'es'} remaining.
END
}
 
sub score ($puzzle, $guess) {
my @score;
for ^$length {
if $puzzle[$_] eq $guess[$_] {
@score.push: $black;
}
elsif $puzzle[$_] eq any(@$guess) {
@score.push: $white;
}
else {
@score.push('-');
}
}
@score.sort.reverse.join: ' ';
}
 
sub clearscr { $*KERNEL ~~ /'win32'/ ?? run('cls') !! run('clear') }
 
sub get-guess { (uc prompt 'Your guess?: ').comb(/@valid/) }
 
sub is-valid (@guess) { so $length == @guess }
 
sub win { say 'You Win! The correct answer is: ', $puzzle; exit }
 
sub lose { say 'Too bad, you ran out of guesses. The solution was: ', $puzzle; exit }
}</lang>
{{out|Sample output}}
<pre>Valid letter, but wrong position: ○ - Correct letter and position: ●
Guess the 4 element sequence containing the letters A B C D E F
Repeats are not allowed. You have 5 guesses remaining.
 
A B C D :: ○ ○ ○ -
C A B E :: ● ○ ○ -
D A E F :: ● ○ - -
B A E C :: ● ○ ○ -
D E B C :: ○ ○ ○ ○
 
Your guess?: cdeb
You Win! The correct answer is: (C D E B)</pre>
 
=={{header|Phix}}==
OTT GUI solution, fully configurable with solver.
<langsyntaxhighlight Phixlang="phix">-- demo/rosetta/mastermind.exw
constant SET_LIMIT = 1_000_000 -- above this, it uses random sampling.
 
Line 1,573 ⟶ 3,309:
IupClose()
end procedure
main()</langsyntaxhighlight>
 
=={{header|Prolog}}==
 
<syntaxhighlight lang="prolog">mastermind :- mastermind(7, 4, 8, no_duplicates).
 
mastermind(Colours, Length, Guesses, Duplicates) :-
between(2, 20, Colours),
between(4, 10, Length),
between(7, 20, Guesses),
member(Duplicates, [allow_duplicates, no_duplicates]),
 
create_board(Colours, Length, Duplicates, Board),
intro(Colours, Length, Duplicates),
play(board(Board, Length, Colours, Guesses), [], 0), !.
 
intro(Colours, Length, Duplicates) :-
format('Guess the code!~n'),
format('There are ~p character types, and ~p letters to guess~n',
[Colours, Length]),
Duplicates = allow_duplicates
-> format('Duplicates are allowed~n~n')
; format('Duplicates are not allowed~n~n').
 
/* Create the combination to be guessed */
create_board(Colours, Length, Duplicates, Board) :-
length(Board, Length),
valid_char_list(Colours, CharSet),
repeat,
maplist(random_alpha(CharSet), Board),
check_for_duplicates(Board, Duplicates).
 
check_for_duplicates(_, allow_dupicates).
check_for_duplicates(Board, no_duplicates) :- is_set(Board).
 
/* Main loop - get the player guess and print out status */
play(board(Board,_,_,MaxGuesses), _, MaxGuesses) :-
write('Sorry, You failed to guess in time...!\nThe code was : '),
maplist(write, Board),
nl.
play(BoardData, PrevGuesses, GuessNum) :-
BoardData = board(_, Length, Colours, MaxGuesses),
GuessNum < MaxGuesses,
ReportedGuess is GuessNum + 1,
format('Guess #~p of #~p: ', [ReportedGuess, MaxGuesses]),
get_player_guess(Length, Colours, Guess),
evaluate_and_print_result(BoardData, PrevGuesses, ReportedGuess, Guess).
 
evaluate_and_print_result(board(Board,_,_,_), _, _,Board) :-
format('Well done! You Guessed Correctly.~n').
evaluate_and_print_result(BoardData, PrevGuesses, NextGuessNum, Guess) :-
BoardData = board(Board, _, _, _),
dif(Board, Guess),
match_guess_to_board(Board, Guess, Diffs),
append(PrevGuesses, [guess(NextGuessNum, Guess, Diffs)], Guesses),
maplist(print_guess, Guesses),
play(BoardData, Guesses, NextGuessNum).
 
/* Get the player guess and validate that it matches the rules */
get_player_guess(Length, Colours, Guess) :-
repeat,
read_line_to_string(user_input, Line),
string_chars(Line, Guess),
 
% validate the correct number of items have been entered
length(Guess, Length),
 
% validate that all the characters are valid for the number of colours
valid_char_list(Colours, ValidCharSet),
subset(Guess, ValidCharSet).
 
/* Predicates to figure out how many places are correct */
match_guess_to_board(Board, Guess, Matches) :-
maplist(guess_differences(Board), Board, Guess, Differences),
sort(0, @>=, Differences, Matches).
 
% Same position, same type
guess_differences(_Board, B, B, 'X').
% Same type, different position
guess_differences(Board, B, G, 'O') :- dif(B, G), member(G, Board).
% Type not on board
guess_differences(Board, B, G, '-') :- dif(B, G), \+ member(G, Board).
 
/* Print out the current progress */
print_guess(guess(NextGuessNumber, Guess, Differences)) :-
format('~w: ', NextGuessNumber),
maplist(format('~w '), Guess),
format(' : '),
maplist(format('~w '), Differences),
nl.
 
/* Utils */
alpha_chars([a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t]).
 
valid_char_list(Colours, CharSet) :-
alpha_chars(AllChars),
truncate_list(AllChars, Colours, CharSet).
 
random_alpha(AllChars, RandomMember) :- random_member(RandomMember, AllChars).
 
truncate_list(_, 0, []).
truncate_list([A|T], N, [A|R]) :-
N > 0,
N1 is N - 1,
truncate_list(T, N1, R).</syntaxhighlight>
{{out}}
<pre>
1 ?- mastermind.
Guess the code!
There are 7 character types, and 4 letters to guess
Duplicates are not allowed
 
Guess #1 of #8: abcd
1: a b c d : X O O -
Guess #2 of #8: acbe
1: a b c d : X O O -
2: a c b e : X O - -
Guess #3 of #8: fgab
1: a b c d : X O O -
2: a c b e : X O - -
3: f g a b : O O - -
Guess #4 of #8: cdfg
1: a b c d : X O O -
2: a c b e : X O - -
3: f g a b : O O - -
4: c d f g : X X O -
Guess #5 of #8: cdfb
1: a b c d : X O O -
2: a c b e : X O - -
3: f g a b : O O - -
4: c d f g : X X O -
5: c d f b : X X O -
Guess #6 of #8: cdaf
1: a b c d : X O O -
2: a c b e : X O - -
3: f g a b : O O - -
4: c d f g : X X O -
5: c d f b : X X O -
6: c d a f : X O O O
Guess #7 of #8: acdf
1: a b c d : X O O -
2: a c b e : X O - -
3: f g a b : O O - -
4: c d f g : X X O -
5: c d f b : X X O -
6: c d a f : X O O O
7: a c d f : X O O O
Guess #8 of #8: adfc
Well done! You Guess Correctly.
true.
</pre>
 
=={{header|Python}}==
{{works with|cpython|3.7.3}}
Tested in Python 3.7.3. Includes input verification.
<syntaxhighlight lang="python">
import random
 
 
def encode(correct, guess):
output_arr = [''] * len(correct)
 
for i, (correct_char, guess_char) in enumerate(zip(correct, guess)):
output_arr[i] = 'X' if guess_char == correct_char else 'O' if guess_char in correct else '-'
 
return ''.join(output_arr)
 
 
def safe_int_input(prompt, min_val, max_val):
while True:
user_input = input(prompt)
 
try:
user_input = int(user_input)
except ValueError:
continue
 
if min_val <= user_input <= max_val:
return user_input
 
 
def play_game():
print("Welcome to Mastermind.")
print("You will need to guess a random code.")
print("For each guess, you will receive a hint.")
print("In this hint, X denotes a correct letter, and O a letter in the original string but in a different position.")
print()
 
number_of_letters = safe_int_input("Select a number of possible letters for the code (2-20): ", 2, 20)
code_length = safe_int_input("Select a length for the code (4-10): ", 4, 10)
 
letters = 'ABCDEFGHIJKLMNOPQRST'[:number_of_letters]
code = ''.join(random.choices(letters, k=code_length))
guesses = []
 
while True:
print()
guess = input(f"Enter a guess of length {code_length} ({letters}): ").upper().strip()
 
if len(guess) != code_length or any([char not in letters for char in guess]):
continue
elif guess == code:
print(f"\nYour guess {guess} was correct!")
break
else:
guesses.append(f"{len(guesses)+1}: {' '.join(guess)} => {' '.join(encode(code, guess))}")
 
for i_guess in guesses:
print("------------------------------------")
print(i_guess)
print("------------------------------------")
 
 
if __name__ == '__main__':
play_game()
 
</syntaxhighlight>
{{out}}
<pre>
Welcome to Mastermind.
You will need to guess a random code.
For each guess, you will receive a hint.
In this hint, X denotes a correct letter, and O a letter in the original string but a different position.
 
Select a number of possible letters for the code (2-20): 4
Select a length for the code (4-10): 4
 
*omitted first guesses*
 
Enter a guess of length 4 (ABCD): cdaa
------------------------------------
1: A A B B => O O - -
------------------------------------
2: C D A A => O X X O
------------------------------------
 
Enter a guess of length 4 (ABCD): ddac
 
Your guess DDAC was correct!
</pre>
 
=={{header|Raku}}==
(formerly Perl 6)
{{works with|Rakudo|2017.01}}
By default, plays classic Mastermind using letters in place of colors. ( 4 chosen from 6, no repeats, 10 guess limit. ) Pass in parameters to modify the game. Enter a string of --length (default 4) letters with or without spaces. Guesses accept lower or upper case.
<syntaxhighlight lang="raku" line>sub MAIN (
Int :$colors where 1 < * < 21 = 6, Int :$length where 3 < * < 11 = 4,
Int :$guesses where 7 < * < 21 = 10, Bool :$repeat = False
) {
my @valid = ('A' .. 'T')[^$colors];
my $puzzle = $repeat ?? @valid.roll($length) !! @valid.pick($length);
my @guesses;
 
my $black = '●';
my $white = '○';
 
loop {
clearscr();
say header();
printf " %{$length * 2}s :: %s\n", @guesses[$_][0], @guesses[$_][1] for ^@guesses;
say '';
lose() if @guesses == $guesses;
my $guess = get-guess();
next unless $guess.&is-valid;
my $score = score($puzzle, $guess);
win() if $score eq ($black xx $length).join: ' ';
@guesses.push: [$guess, $score];
}
 
sub header {
my $num = $guesses - @guesses;
qq:to/END/;
Valid letter, but wrong position: ○ - Correct letter and position: ●
Guess the {$length} element sequence containing the letters {@valid}
Repeats are {$repeat ?? '' !! 'not '}allowed. You have $num guess{ $num == 1 ?? '' !! 'es'} remaining.
END
}
 
sub score ($puzzle, $guess) {
my @score;
for ^$length {
if $puzzle[$_] eq $guess[$_] {
@score.push: $black;
}
elsif $puzzle[$_] eq any(@$guess) {
@score.push: $white;
}
else {
@score.push('-');
}
}
@score.sort.reverse.join: ' ';
}
 
sub clearscr { $*KERNEL ~~ /'win32'/ ?? run('cls') !! run('clear') }
 
sub get-guess { (uc prompt 'Your guess?: ').comb(/@valid/) }
 
sub is-valid (@guess) { so $length == @guess }
 
sub win { say 'You Win! The correct answer is: ', $puzzle; exit }
 
sub lose { say 'Too bad, you ran out of guesses. The solution was: ', $puzzle; exit }
}</syntaxhighlight>
{{out|Sample output}}
<pre>Valid letter, but wrong position: ○ - Correct letter and position: ●
Guess the 4 element sequence containing the letters A B C D E F
Repeats are not allowed. You have 5 guesses remaining.
 
A B C D :: ○ ○ ○ -
C A B E :: ● ○ ○ -
D A E F :: ● ○ - -
B A E C :: ● ○ ○ -
D E B C :: ○ ○ ○ ○
 
Your guess?: cdeb
You Win! The correct answer is: (C D E B)</pre>
 
=={{header|REXX}}==
More checks could have been added &nbsp; (for illegal inputs and illegal options).
<langsyntaxhighlight lang="rexx">/*REXX pgm scores mastermind game with a human or CBLFs (Carbon Based Life Forms). */
parse arg let wid mxG oRep seed _ /*obtain optional arguments from the CL*/
arg . . . rep . /*get uppercase 4th argument " " " */
Line 1,654 ⟶ 3,706:
if val > mx then call ser ? "has a value greater than " mx /*◄■■■■■■ optional vetting.*/
if ?=='REP' & \datatype(val,W) then call ser "Value for REPEATS isn't valid: " oRep /*◄■■■■■■ optional vetting.*/
return 1</langsyntaxhighlight>
'''output'''
<pre>
Line 1,711 ⟶ 3,763:
 
=={{header|Ring}}==
<langsyntaxhighlight lang="ring">
# Project : Mastermind
 
Line 1,805 ⟶ 3,857:
next
see nl
</syntaxhighlight>
</lang>
Output:
<pre>
Line 1,817 ⟶ 3,869:
Well done!
End of game
</pre>
 
=={{header|Rust}}==
{{libheader|rand}}
<syntaxhighlight lang="rust">extern crate rand;
 
use rand::prelude::*;
use std::io;
 
fn main() {
let mut input_line = String::new();
let colors_n;
let code_len;
let guesses_max;
let colors_dup;
 
loop {
println!("Please enter the number of colors to be used in the game (2 - 20): ");
input_line.clear();
io::stdin()
.read_line(&mut input_line)
.expect("The read line failed.");
match (input_line.trim()).parse::<i32>() {
Ok(n) => {
if n >= 2 && n <= 20 {
colors_n = n;
break;
} else {
println!("Outside of range (2 - 20).");
}
}
Err(_) => println!("Invalid input."),
}
}
let colors = &"ABCDEFGHIJKLMNOPQRST"[..colors_n as usize];
 
println!("Playing with colors {}.\n", colors);
 
loop {
println!("Are duplicated colors allowed in the code? (Y/N): ");
input_line.clear();
io::stdin()
.read_line(&mut input_line)
.expect("The read line failed.");
if ["Y", "N"].contains(&&input_line.trim().to_uppercase()[..]) {
colors_dup = input_line.trim().to_uppercase() == "Y";
break;
} else {
println!("Invalid input.");
}
}
println!(
"Duplicated colors {}allowed.\n",
if colors_dup { "" } else { "not " }
);
loop {
let min_len = if colors_dup { 4 } else { 4.min(colors_n) };
let max_len = if colors_dup { 10 } else { 10.min(colors_n) };
println!(
"Please enter the length of the code ({} - {}): ",
min_len, max_len
);
input_line.clear();
io::stdin()
.read_line(&mut input_line)
.expect("The read line failed.");
match (input_line.trim()).parse::<i32>() {
Ok(n) => {
if n >= min_len && n <= max_len {
code_len = n;
break;
} else {
println!("Outside of range ({} - {}).", min_len, max_len);
}
}
Err(_) => println!("Invalid input."),
}
}
println!("Code of length {}.\n", code_len);
loop {
println!("Please enter the number of guesses allowed (7 - 20): ");
input_line.clear();
io::stdin()
.read_line(&mut input_line)
.expect("The read line failed.");
match (input_line.trim()).parse::<i32>() {
Ok(n) => {
if n >= 7 && n <= 20 {
guesses_max = n;
break;
} else {
println!("Outside of range (7 - 20).");
}
}
Err(_) => println!("Invalid input."),
}
}
println!("{} guesses allowed.\n", guesses_max);
 
let mut rng = rand::thread_rng();
let mut code;
if colors_dup {
code = (0..code_len)
.map(|_| ((65 + rng.gen_range(0, colors_n) as u8) as char))
.collect::<Vec<_>>();
} else {
code = colors.chars().collect::<Vec<_>>();
code.shuffle(&mut rng);
code = code[..code_len as usize].to_vec();
}
//code = vec!['J', 'A', 'R', 'D', 'A', 'N', 'I'];
//println!("Secret code: {:?}", code);
let mut guesses: Vec<(String, String)> = vec![];
let mut i = 1;
loop {
println!("Your guess ({}/{})?: ", i, guesses_max);
input_line.clear();
io::stdin()
.read_line(&mut input_line)
.expect("The read line failed.");
let mut guess = input_line.trim().to_uppercase();
if guess.len() as i32 > code_len {
guess = guess[..code_len as usize].to_string();
}
let guess_v = guess.chars().collect::<Vec<char>>();
let res = evaluate(&code, &guess_v);
guesses.push((guess, res.clone()));
let width = 8 + guesses_max.to_string().len() + code_len as usize * 2;
println!("{}", "-".repeat(width));
for (i, guess) in guesses.iter().enumerate() {
let line = format!(
" {:w1$} : {:w2$} : {:w2$} ",
i + 1,
guess.0,
guess.1,
w1 = guesses_max.to_string().len(),
w2 = code_len as usize
);
println!("{}", line);
}
println!("{}", "-".repeat(width));
if res == "X".repeat(code_len as usize) {
println!("You won! Code: {}", code.into_iter().collect::<String>());
break;
}
i += 1;
if i > guesses_max {
println!("You lost. Code: {}", code.into_iter().collect::<String>());
break;
}
}
}
 
fn evaluate(code: &[char], guess: &[char]) -> String {
let mut res: Vec<char> = vec![];
for i in 0..guess.len() {
if guess[i] == code[i] {
res.push('X');
} else if code.contains(&guess[i]) {
res.push('O');
} else {
res.push('-');
}
}
res.sort_by(|a, b| b.cmp(a));
res.into_iter().collect()
}</syntaxhighlight>
{{out}}
<pre>
Please enter the number of colors to be used in the game (2 - 20):
20
Playing with colors ABCDEFGHIJKLMNOPQRST.
 
Are duplicated colors allowed in the code? (Y/N):
n
Duplicated colors not allowed.
 
Please enter the length of the code (4 - 10):
10
Code of length 10.
 
Please enter the number of guesses allowed (7 - 20):
20
20 guesses allowed.
 
Your guess (1/20)?:
abcdefghi
------------------------------
1 : ABCDEFGHI : OOOOOO---
------------------------------
<...>
Your guess (20/20)?:
ipgecnmhdk
------------------------------
1 : ABCDEFGHI : OOOOOO---
2 : ABCDE : OOO--
3 : ABC : O--
4 : DEBF : OO--
5 : DEAG : OOO-
6 : DEAH : OOO-
7 : DEAGH : OOOO-
8 : DEGHI : XOOOO
9 : JKLMN : OOO--
10 : JKL : O--
11 : K : O
12 : DEGHIK : XOOOOO
13 : MN : OO
14 : OPQ : X--
15 : QRS : ---
16 : PT : O-
17 : PEGHIKCMND : XOOOOOOOOO
18 : HKMNICDPEG : OOOOOOOOOO
19 : EGNHKMPDCI : OOOOOOOOOO
20 : IPGECNMHDK : XXXXXXXXOO
------------------------------
You lost. Code: IPGECHMNDK
</pre>
 
=={{header|SQL}}==
<syntaxhighlight lang="sql">
-- Create Table
-- Distinct combination
--- R :Red, B :Blue, G: Green, V: Violet, O: Orange, Y: Yellow
DROP TYPE IF EXISTS color cascade;CREATE TYPE color AS ENUM ('R', 'B', 'G', 'V', 'O', 'Y');
 
DROP TABLE IF EXISTS guesses cascade ; CREATE TABLE guesses (
first color,
second color,
third color ,
fourth color
);
CREATE TABLE mastermind () inherits (guesses);
 
INSERT INTO mastermind values ('G', 'B', 'R', 'V');
 
 
INSERT INTO guesses values ('Y', 'Y', 'B', 'B');
INSERT INTO guesses values ('V', 'R', 'R', 'Y');
INSERT INTO guesses values ('G', 'V', 'G', 'Y');
INSERT INTO guesses values ('R', 'R', 'V', 'Y');
INSERT INTO guesses values ('B', 'R', 'G', 'V');
INSERT INTO guesses values ('G', 'B', 'R', 'V');
 
 
--- Matches Black
CREATE OR REPLACE FUNCTION check_black(guesses, mastermind) RETURNS integer AS $$
SELECT (
($1.first = $2.first)::int +
($1.second = $2.second)::int +
($1.third = $2.third)::int +
($1.fourth = $2.fourth)::int
);
$$ LANGUAGE SQL;
 
--- Matches White
CREATE OR REPLACE FUNCTION check_white(guesses, mastermind) RETURNS integer AS $$
SELECT (
case when ($1.first = $2.first) then 0 else 0 end +
case when ($1.second = $2.second) then 0 else 0 end +
case when ($1.third = $2.third) then 0 else 0 end +
case when ($1.fourth = $2.fourth) then 0 else 0 end +
case when ($1.first != $2.first) then (
$1.first = $2.second or
$1.first = $2.third or
$1.first = $2.fourth
)::int else 0 end +
case when ($1.second != $2.second) then (
$1.second = $2.first or
$1.second = $2.third or
$1.second = $2.fourth
)::int else 0 end +
case when ($1.third != $2.third) then (
$1.third = $2.first or
$1.third = $2.second or
$1.third = $2.fourth
)::int else 0 end +
case when ($1.fourth != $2.fourth) then (
$1.fourth = $2.first or
$1.fourth = $2.second or
$1.fourth = $2.third
)::int else 0 end
) from guesses
$$ LANGUAGE SQL;
 
 
 
SELECT guesses,
check_black(guesses.*, mastermind.*),
check_white(guesses.*, mastermind.*)
FROM guesses, mastermind
</syntaxhighlight>
 
=={{header|Wren}}==
{{trans|Kotlin}}
{{libheader|Wren-ioutil}}
{{libheader|Wren-str}}
<syntaxhighlight lang="wren">import "random" for Random
import "./ioutil" for Input
import "./str" for Str
 
var Rand = Random.new()
 
class Mastermind {
construct new(codeLen, colorsCnt, guessCnt, repeatClr) {
var color = "ABCDEFGHIJKLMNOPQRST"
_codeLen = codeLen.clamp(4, 10)
var cl = colorsCnt
if (!repeatClr && cl < _codeLen) cl = _codeLen
_colorsCnt = cl.clamp(2, 20)
_guessCnt = guessCnt.clamp(7, 20)
_repeatClr = repeatClr
_colors = color.take(_colorsCnt).join()
_combo = ""
_guesses = []
_results = []
}
 
play() {
var win = false
_combo = getCombo_()
while (_guessCnt != 0) {
showBoard_()
if (checkInput_(getInput_())) {
win = true
break
}
_guessCnt = _guessCnt - 1
}
System.print("\n\n--------------------------------")
if (win) {
System.print("Very well done!\nYou found the code: %(_combo)")
} else {
System.print("I am sorry, you couldn't make it!\nThe code was: %(_combo)")
}
System.print("--------------------------------\n")
}
 
showBoard_() {
for (x in 0..._guesses.count) {
System.print("\n--------------------------------")
System.write("%(x + 1): ")
for (y in _guesses[x]) System.write("%(y) ")
System.write(" : ")
for (y in _results[x]) System.write("%(y) ")
var z = _codeLen - _results[x].count
if (z > 0) System.write("- " * z)
}
System.print("\n")
}
 
getInput_() {
while (true) {
var a = Str.upper(Input.text("Enter your guess (%(_colors)): ", 1)).take(_codeLen)
if (a.all { |c| _colors.contains(c) } ) return a.join()
}
}
 
checkInput_(a) {
_guesses.add(a.toList)
var black = 0
var white = 0
var gmatch = List.filled(_codeLen, false)
var cmatch = List.filled(_codeLen, false)
for (i in 0..._codeLen) {
if (a[i] == _combo[i]) {
gmatch[i] = true
cmatch[i] = true
black = black + 1
}
}
for (i in 0..._codeLen) {
if (gmatch[i]) continue
for (j in 0..._codeLen) {
if (i == j || cmatch[j]) continue
if (a[i] == _combo[j]) {
cmatch[j] = true
white = white + 1
break
}
}
}
var r = []
r.addAll(("X" * black).toList)
r.addAll(("O" * white).toList)
_results.add(r)
return black == _codeLen
}
 
getCombo_() {
var c = ""
var clr = _colors
for (s in 0..._codeLen) {
var z = Rand.int(clr.count)
c = c + clr[z]
if (!_repeatClr) Str.delete(clr, z)
}
return c
}
}
 
var m = Mastermind.new(4, 8, 12, false)
m.play()</syntaxhighlight>
 
{{out}}
Sample game:
<pre>
Enter your guess (ABCDEFGH): abcd
 
--------------------------------
1: A B C D : X - - -
 
Enter your guess (ABCDEFGH): efgh
 
--------------------------------
1: A B C D : X - - -
--------------------------------
2: E F G H : O O - -
 
Enter your guess (ABCDEFGH): aefa
 
--------------------------------
1: A B C D : X - - -
--------------------------------
2: E F G H : O O - -
--------------------------------
3: A E F A : X X - -
 
Enter your guess (ABCDEFGH): aagh
 
--------------------------------
1: A B C D : X - - -
--------------------------------
2: E F G H : O O - -
--------------------------------
3: A E F A : X X - -
--------------------------------
4: A A G H : X O O O
 
Enter your guess (ABCDEFGH): agah
 
--------------------------------
1: A B C D : X - - -
--------------------------------
2: E F G H : O O - -
--------------------------------
3: A E F A : X X - -
--------------------------------
4: A A G H : X O O O
--------------------------------
5: A G A H : X X O O
 
Enter your guess (ABCDEFGH): agha
 
 
--------------------------------
Very well done!
You found the code: AGHA
--------------------------------
</pre>
 
=={{header|zkl}}==
{{trans|C++}}
<langsyntaxhighlight lang="zkl">class MasterMind{
fcn init(code_len,guess_count){
var codeLen =code_len.max(4).min(10);
Line 1,867 ⟶ 4,377:
return(black==codeLen,"X"*black + "O"*white)
}
}(4,12).play();</langsyntaxhighlight>
{{out}}
<pre>
1,983

edits