Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import tkinter as tk
- from random import choices
- import itertools as it
- class Mastermind(tk.Frame):
- def __init__(self, master, holes=5, colours=8, guesses=12, bg="white", fg="black", **kwargs):
- self.numberOfHoles = holes
- self.numberOfColours = colours
- self.numberOfGuesses = guesses
- self.bg = bg
- self.fg = fg
- self.master = master
- self.colours = ["#9E5D00", "#FF0000", "#FF7F00", "#FFFF00", "#00FF00",
- "#0000FF", "#FF00FF", "#8C44FF", "#FFFFFF", "#000000"][:self.numberOfColours]
- self.reset_cycles()
- self.answer = choices(self.colours, k=self.numberOfHoles)
- super().__init__(self.master, bg=self.bg, **kwargs)
- print(self.answer)
- self.create_gui()
- def create_gui(self):
- self.allGuesses = [tk.Frame(self, bg=self.bg) for _ in range(self.numberOfGuesses)]
- self.allMarks = [tk.Frame(self, bg=self.bg) for _ in range(self.numberOfGuesses)]
- self.answerFrame = tk.Frame(self, bg=self.bg)
- self.answerCover = tk.Frame(self, bg=self.fg, relief=tk.RAISED)
- self.allGuessPins = [[tk.Label(self.allGuesses[i], width=2, height=1, bg="grey", relief=tk.SUNKEN)
- for _ in range(self.numberOfHoles)]
- for i in range(self.numberOfGuesses)]
- self.allMarkPins = [[tk.Label(self.allMarks[i], width=1, height=1, bg="lightgrey", relief=tk.SUNKEN)
- for _ in range(self.numberOfHoles)]
- for i in range(self.numberOfGuesses)]
- self.answerPins = [tk.Label(self.answerFrame, width=2, height=1, bg=colour, relief=tk.RAISED) for colour in self.answer]
- self.guessBtn = tk.Button(self, text="Guess", command=self.next_guess, bg=self.bg, fg=self.fg)
- self.activeGuess = 0
- for rowIndex in range(self.numberOfGuesses):
- for holeIndex in range(self.numberOfHoles):
- self.allGuessPins[rowIndex][holeIndex].grid(row=0, column=holeIndex, padx=1, pady=4)
- self.allMarkPins[rowIndex][holeIndex].grid(row=0, column=holeIndex, padx=1, pady=4)
- tk.Label(self, text=str(rowIndex+1), bg=self.bg, fg=self.fg).grid(row=self.numberOfGuesses-rowIndex, column=0)
- self.allGuesses[rowIndex].grid(row=rowIndex+1, column=1)
- self.allMarks[rowIndex].grid(row=rowIndex+1, column=3)
- for i, a in enumerate(self.answerPins):
- a.grid(row=0, column=i, padx=1)
- tk.Label(self, text=" ", bg=self.bg).grid(row=0, column=2)
- tk.Label(self, text=" ", bg=self.bg).grid(row=0, column=4)
- for a in [tk.Label(self.answerCover, width=2, height=1, bg=self.fg) for _ in range(self.numberOfHoles)]:
- a.pack(side=tk.LEFT, padx=1)
- self.answerCover.grid(row=0, column=1, pady=15)
- self.guessBtn.grid(column=1, row=999, pady=10)
- self.next_guess(start=True)
- def next_guess(self, start=False):
- # Check there are no blanks
- for colour in self.get_pin_colours():
- if colour == "grey" and not start:
- return None
- # Stop responding to mouse button and remove highlighting
- self.reset_cycles()
- self.allGuesses[self.activeGuess].config(bg=self.bg)
- for pin in self.allGuessPins[self.activeGuess]:
- pin.unbind("<1>")
- pin["cursor"] = ""
- # Add the mark pins for the guess
- score = self.score_guess(self.get_pin_colours(), self.answer)
- if not start and len(score) != 0:
- score = self.score_guess(self.get_pin_colours(), self.answer)
- for i, pin in enumerate(self.allMarkPins[self.activeGuess]):
- if i > len(score)-1:
- break
- pin.config(bg=score[i], relief=tk.RAISED)
- # Check for a win
- if score == ["Black" for _ in range(self.numberOfHoles)]:
- self.answerCover.grid_forget()
- self.answerFrame.grid(row=0, column=1, pady=15)
- self.guessBtn["command"] = None
- return None
- # Move the guess up 1, bind mouse button and highlight row
- try:
- self.activeGuess -= 1
- self.allGuesses[self.activeGuess].config(bg=self.fg)
- for i, pin in enumerate(self.allGuessPins[self.activeGuess]):
- pin.bind("<1>", lambda event, i=i: self.change_pin_colour(event, i))
- pin["cursor"] = "hand"
- except IndexError:
- raise NotImplementedError()
- # add lose condition
- @staticmethod
- def score_guess(guess, answer):
- answer = answer.copy()
- blacks = ["Black" for secret, guess_item in zip(answer, guess) if secret == guess_item]
- whites = []
- for guess_item in guess:
- if guess_item in answer:
- answer[answer.index(guess_item)] = None
- whites.append("White")
- return blacks + whites[:-len(blacks)]
- def get_pin_colours(self):
- return [pin["bg"] for pin in self.allGuessPins[self.activeGuess]]
- def change_pin_colour(self, event, i):
- event.widget.config(bg=next(self.colourCycles[i]), relief=tk.RAISED)
- def reset_cycles(self):
- self.colourCycles = it.tee(it.cycle(self.colours), self.numberOfHoles)
- if __name__ == "__main__":
- root = tk.Tk()
- root.title("Mastermind")
- x = Mastermind(root)
- x.pack()
- root.mainloop()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement