# Master Mind on Python

I made Master Mind on Python!

``````import random

color = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"]

def gen_colors(code_size):
code = ""
for i in range(code_size):
if i > 25:
return code
code += color[i]
return code

def gen_code(code_size, colors):
code = ""
for i in range(code_size):
code += colors[random.randint(0, len(colors) - 1)]
return code

def check_guess(guess, code_size, colors):
if len(guess) != code_size:
return False
for i in range(len(guess)):
if guess[i] not in colors:
return False
return True

def score_guess(code, guess):
correct = 0 # correct is count of right letter in its place
correct1 = 0 # correct1 is count of right letter out of place
for i in range(0, len(code)):
if guess[i] == code[i]:
correct += 1
if guess[i] in code and guess[i] != code[i]:
correct1 += 1
return tuple([correct, correct1])

def play_cli(code_size, nb_colors):
attempts = 0
possible_colors = gen_colors(nb_colors)
print(f"Possible colors are {possible_colors}")
print(f"Code is size {code_size}.")
code = gen_code(code_size, possible_colors)
while True:
guess = str(input())
if guess == "fall":
print(f"The code is {code}")
break
attempts += 1
if guess == code:
print(f"Congrats, you won after {attempts} attempts!")
break
if check_guess(guess, code_size, possible_colors) == True:
print(score_guess(code, guess))
else:
attempts -= 1
print("Wrong size or color!")
``````

`play_cli(4, 6)` should output:

``````Possible colors are ABCDEF
Code is size 4.
``````

But it has a inaccuracy:

Letās say the random code is `FFEE`,
We introduce `FFFF`,

It print:
`(2, 2) # 2 letters in place, 2 letters out of place`

But I want it to print:
`(2, 0) # 2 letters in place`

Ahh, this is a game my Mum and I spent many many hours playing, in my childhood! The memories. (Side note: We actually played a variant where the colours had to be unique. It makes the logic more fun IMO.)

So, the logic youāre having trouble with is here:

``````def score_guess(code, guess):
correct = 0 # correct is count of right letter in its place
correct1 = 0 # correct1 is count of right letter out of place
for i in range(0, len(code)):
if guess[i] == code[i]:
correct += 1
if guess[i] in code and guess[i] != code[i]:
correct1 += 1
return tuple([correct, correct1])
``````

The thing is really quite simple. The insertion of a single word will do it. If a guess is precisely correct, then it isnāt also partly correct. To be precise, a particular iteration through this loop should only be able to increment one of the two scores - if it increments `correct`, it should not even attempt to increment `correct1`.

This then allows another simplification: the second condition on the `correct1` check will no longer be necessary.

While youāre at it, there are a couple of other ways you could do this iteration. The classic alternative to `range(len(x))` is to use `enumerate`, but in this case, what youāre really doing is iterating simultaneously over both the code and the guess - that is to say: `for c, g in zip(code, guess):`

With that, and a few other small changes, hereās how I would write that function:

``````def score_guess(code, guess):
correct = misplaced = 0
for c, g in zip(code, guess):
if c == g: correct += 1
elif g in code: misplaced += 1
return correct, misplaced
``````

Note that constructing a list and then building a tuple from that list is unnecessary; you can simply return the two values with a comma between them, and youāll get a tuple.

Hope that helps!

1 Like

Thank you for the answer, it is short and informative.
But the problem remains:

``````Possible colors are ABCDEF
Code is size 4.
FFFF
(2, 0)
``````

Ah, true. I was actually solving the opposite bug; that one still remains.

So, what you need to do is āuse upā one of the entries in the code whenever you give a score based on it. There are a few ways you can do this, including maintaining a counter, and turning the code into a list which you mutate as you mark them off.

1 Like

I will try.