reCreating Mastermind in Python IDLE using built-in random module

Mastermind is a two-player game revolving around a secret combination of four colored pegs. One player makes a series of guesses at that combination and the correctness is evaluated by the second player utilizing black and white pegs. A black peg indicates a correctly-colored peg in the correct position, and white peg indicates a correctly-colored peg in the wrong position.

Combinations and guess in this program will be indicates by four-letter strings, where each letter is the initial of a color: Red, Yellow, Blue, Green, Purple, White


The first step in building the program requires some general housekeeping – defining variables, importing necessary modules, and developing systems to prevent errors or impossible games.

colors = ['R', 'Y', 'B', 'G', 'P', 'W']
import random

def is_valid(combination):
    '''identifies whether combination is valid:
       four letters from the list defined above
       Returns True or False accordingly'''
    if len(combination) != 4:
        return False
    else:
        valid = True
        for letter in combination:
            if letter not in colors:
                valid = False
        return valid

def input_combination():
    '''asks the user for a combination,
       and continues to ask if the input is invalid'''
    combination = input("What would you like to guess? ")
    while not is_valid(combination):
        print("Guess must be four letters from "+ ", ".join(colors))
        combination = input("Try again: ")
    return combination



Now it’s time to use the random module to quickly and easily create lists of valid combinations without having to type everything out by hand. Also allows for easy modification of code, such as changing the valid colors list.

def all_combinations():
    '''generates a list of all valid combinations'''
    combo_list = []
    for first in colors:
        for second in colors:
            for third in colors:
                for fourth in colors:
                    combo_list.append(first+second+third+fourth)
    return combo_list

def random_combination():
    '''Generates random combination of four colors,
       random.select() is NOT chosen, because it disallows duplicaties'''
    return (random.choice(colors) + random.choice(colors)
         +  random.choice(colors) + random.choice(colors))




Examine each position to see if colors match (black pegs), removing matching pegs from both lists when found so as not to score extra white pegs. Then, repeat for white pegs and return both.

def check_guess(guess, answer):
    '''compares a guessed combination with the right answer'''
  
#makes editable copies of each list  
    answer_copy = list(answer)     
    guess_copy = list(guess)
    black = 0
    white = 0

    for ind in range(len(guess_copy)):
        if guess_copy[ind] == answer_copy[ind]:
            #removes correct answers from lists so won't be double counted
              when checking white pegs
            guess_copy[ind] = "?"
            answer_copy[ind] = "*"
            black = black + 1

    for ind in range(len(guess_copy)):
        if guess_copy[ind] in answer_copy:
            answer_ind = answer_copy.index(guess_copy[ind])
            answer_copy[answer_ind] = "@"
            guess_copy[ind] = "#"
            white = white + 1

    return black, white



Now to create a function where the keyboard user tries to guess a combination chosen by the computer

def user_guesses():
    '''A game of mastermind where the keyboard user
       tries to guess a combination chosen by the computer.'''

    computer_pick = random_combination()
    user_pick = input_combination()
    user_tries = 0
    while user_pick != computer_pick:
        blackwhite = check_guess(user_pick,computer_pick)
        print(f"""Black pegs: {blackwhite[0]}
White pegs: {blackwhite[1]}""")
        user_tries = user_tries + 1
        user_pick = input_combination()   

    print("You got it!")
    return user_tries



Now to create a function where computer guesses at combination chosen by keyboard user

def computer_guesses():
    # Start with all possible guesses
    pool = all_combinations()
    computer_pick = random_combination()
    black_user = 0
    computer_tries = 0
    
    # If the answer is not yet known
    while len(pool) > 1:
        print("My guess is " + computer_pick)
        computer_tries = computer_tries + 1
        black_user = int(input("How many black pegs? "))
        white_user = int(input("How many white pegs? "))
        for n in reversed(range(len(pool))):
            blackwhite = check_guess(pool[n],computer_pick)
            if blackwhite[0] != black_user or blackwhite[0] + blackwhite[1] != black_user + white_user:
                pool.pop(n)
        if len(pool) > 1:    
            computer_pick = random.choice(pool)

    # Report the solution when found
    if len(pool) == 0:
        print("I could not find any answer that matches your responses.")
    else:
        print("I think I have it!  Your combination is ",pool[0])

    return computer_tries


One final block of code that will be used to check how the logic of the rest of the code is functioning, ie checking that the program will return the correct number of black and white pegs.

def test_check_guess(guess,answer,result,message):
    response = check_guess(guess,answer)
    if response == result:       # It worked!
        return True
    elif len(response) != 2:
        print('Did not get black and white pegs comparing',guess,'to',answer)
        return False
    else:
        print('Got response of',response,'comparing',guess,'to',answer)
        print('Correct result would be',result,'--',message)
        return False

def test_checker():
    test_check_guess('RBBB','RGGG',(1,0),'cannot find the black peg')
    test_check_guess('BBBR','GGGR',(1,0),'cannot find the black peg')
    test_check_guess('RRBB','RRGG',(2,0),'did you find both black pegs?')
    test_check_guess('RBBR','RGGR',(2,0),'two black pegs cannot also be white')
    test_check_guess('RRRR','RRRR',(4,0),'four black pegs cannot also be white')
    test_check_guess('RRBB','GGRR',(0,2),'only one white peg per guess peg')
    test_check_guess('RBBB','GGRR',(0,1),'only one white peg per guess peg')
    test_check_guess('RRBB','GGGR',(0,1),'only one white peg per answer peg')
    test_check_guess('RBYW','BYWG',(0,3),'must be able to find all the colors')
    test_check_guess('RBYW','WRBY',(0,4),'must be able to find all the colors')
    test_check_guess('RBYW','RYWB',(1,3),'do not count black peg as white also')
    test_check_guess('RRRR','RGGG',(1,0),'do not count black peg as white also')
    test_check_guess('RGGG','RRRR',(1,0),'do not count black peg as white also')
    test_check_guess('RRRR','GGGR',(1,0),'do not count black peg as white also')
    test_check_guess('GGGR','RRRR',(1,0),'do not count black peg as white also')

test_checker()


Finally, I put it all together. Opening the program will initiate a two-part game, where the keyboard user first tries to guess the computers combination and then has the computer guess at their combination. Whoever (user or computer) guesses the opponent’s combination is fewer tries wins!

print("Welcome to Mastermind!")
yesno = 'y'
while yesno in ['y','Y']:
    print("Try to guess my combination!")
    print("The color choices are: " + ", ".join(colors))
    user_tries = user_guesses()
    print("My turn, to guess at yours!")
    computer_tries = computer_guesses()
    if user_tries < computer_tries:
        print(f"You win! I got it in {computer_tries} and you took {user_tries}")
    elif user_tries > computer_tries:
        print(f"You lose! I got it in {computer_tries} and you took {user_tries}")
    else:
        print(f"We tied! We both took {computer_tries}")
    yesno = input("Play again? ")


Good luck! The computer can usually guess the correct combo in roughly 4 tries!

Leave a Reply

Your email address will not be published. Required fields are marked *