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();