RosettaCodeData/Task/Mastermind/Zkl/mastermind.zkl

48 lines
1.7 KiB
Plaintext

class MasterMind{
fcn init(code_len,guess_count){
var codeLen =code_len.max(4).min(10);
var guessCnt=guess_count.max(7).min(20);
var colors ="ABCDEFGHIJKLMNOPQRST"[0,codeLen];
}
fcn play{
guesses,win,blackWhite:=List(),False,Void;
code:=codeLen.pump(String,'wrap(_){ colors[(0).random(codeLen)] });
do(guessCnt){
str:=getInput();
win,blackWhite = checkInput(str,code);
guesses.append(T(str,blackWhite));
showBoard(guesses);
if(win) break;
}
if(win) println("--------------------------------\n",
"Very well done!\nYou found the code: ",code);
else println("--------------------------------\n",
"I am sorry, you didn't discover the code!\nThe code was: ",code);
}
fcn [private] showBoard(guesses){
foreach n,gbw in ([1..].zip(guesses)){
guess,blackWhite := gbw;
println("%2d: %s :% s %s".fmt(n,
guess.split("").concat(" "), blackWhite.split("").concat(" "),
"- "*(codeLen - blackWhite.len())));
}
}
fcn [private] getInput{
while(True){
a:=ask("Enter your guess (" + colors + "): ").toUpper()[0,codeLen];
if(not (a-colors) and a.len()>=codeLen) return(a);
}
}
fcn [private] checkInput(guess,code){
// black: guess is correct in both color and position
// white: correct color, wrong position
matched,black := guess.split("").zipWith('==,code), matched.sum(0);
// remove black from code, prepend null to make counting easy
code = L("-").extend(matched.zipWith('wrap(m,peg){ m and "-" or peg },code));
white:=0; foreach m,p in (matched.zip(guess)){
if(not m and (z:=code.find(p))){ white+=1; code[z]="-"; }
}
return(black==codeLen,"X"*black + "O"*white)
}
}(4,12).play();