tkinter and scrabble solver problems
class, python, python-3.3, tkinter
Solution
Although I removed the scrollbar ( I guess you will figure out how to add that too) I completely rewrote your code, to be more pythonic, and easier to read and write. However I tried to stick to your code as much as possible.
I guess it is working now:
Here is the `dictionary.dat` I used:
beast
lemon
ape
apple
sea
pea
orange
bat
And here is the code itself:
# Import python modules
import tkinter
import tkinter.messagebox
from collections import Counter
# Module level constants
SCORES = {'A': 1, 'C': 3, 'B': 3, 'E': 1, 'D': 2, 'G': 2, 'F': 4, 'I': 1,
'H': 4, 'K': 5, 'J': 8, 'M': 3, 'L': 1, 'O': 1, 'N': 1, 'Q': 10,
'P': 3, 'S': 1, 'R': 1, 'U': 1, 'T': 1, 'W': 4, 'V': 4, 'Y': 4,
'X': 8, 'Z': 10}
class App(tkinter.Tk):
def __init__(self, word_list, *args, **kwargs):
# Initialize parent class by passing instance as first argument
tkinter.Tk.__init__(self, *args, **kwargs)
# Store values
self.word_list = word_list
# Setup main window
self.title('Scrabble Solver')
# Create widgets
rack_label = tkinter.Label(self, text='Enter your rack')
self.rack_entry = tkinter.Entry(self)
rack_button = tkinter.Button(self, text='Enter', command=self.search)
quit_button = tkinter.Button(self, text='Quit', command=self.quit)
self.valid_list = tkinter.Listbox(self, width=40, font='Courier')
# Place widgets
rack_label.grid(row=0, column=0, sticky=tkinter.W)
self.rack_entry.grid(row=1, column=0, sticky=tkinter.W)
rack_button.grid(row=1, column=1, sticky=tkinter.W)
quit_button.grid(row=1, column=2, sticky=tkinter.W)
self.valid_list.grid(row=2, columnspan=3, sticky=tkinter.W)
def run(self):
# Enter event loop
self.mainloop()
def error(self):
# Throw and error message dialog
tkinter.messagebox.showinfo('You have entered too many letters!')
def search(self):
# Cleanup up valid list
self.valid_list.delete(0, tkinter.END)
# Get data of entry, and make them lower case
rack = self.rack_entry.get().lower()
# Check length of data
if len(rack) <= 8:
return self.find_valid_words(rack)
self.error()
def find_valid_words(self, rack):
# Create a dictionary for valid words and its values
valid = {}
rack_chars = Counter(rack)
for word in self.word_list:
word_chars = Counter(word)
if word_chars == word_chars & rack_chars:
valid[word] = sum(SCORES[letter.upper()] for letter in word)
# Sort the results and insert them into the list box
if valid:
for word, score in sorted(valid.items(), key=lambda v: v[1], reverse=True):
self.valid_list.insert(tkinter.END, '{:<10} {}'.format(word, score))
else:
self.valid_list.insert(tkinter.END, 'No results found.')
if __name__ == '__main__':
# Open dictionary file and scan for words
with open('dictionary.dat', 'r') as f:
all_words = [word for word in f.read().split()]
# Create instance and call run method
App(all_words).run()
Problem
I have had to learn python 3.3.3 for a logic and design class. I am extremely new at programming and the code below is the culmination of what ive learned on my own in 10 weeks. I had my program working fine at a procedural level with out a GUI. my program was a typical scrabble solver. I just am having a horrible time with tkinter. I need to take my input from the entry to the main module run through and input the results to a listbox. i even gave up on passing parameters from the class tot he main so i set the rack and results to a global var. I understand that this might be too much of hassle for someone to help but any help i get to get this done before finals would be greatly appreciated. thank you in advance. ``` #only reason these are global is because im having trouble with tkinter and #passing the proper parameters to the main module global results global rack import tkinter as tk #class for GUI class application: def __init__(self): self.main=tk.Tk() #top fram includes rack label, rack entry, rack enter button and quit button self.top_frame = tk.Frame(self.main) self.main.title('Scrabble Solver') self.main.geometry('300x300') self.main.wm_iconbitmap('favicon.ico') self.racklbl = tk.Label(self.top_frame, text="Enter your rack") self.racklbl.pack() self.rackent=tk.Entry(self.top_frame) self.rackent.pack(side="left") self.rackbtn = tk.Button(self.top_frame, text = "Enter", command=self.getRackData) self.rackbtn.pack(side="left") self.top_frame.pack() #bottom frame includes listbox for results display and scrollbar self.bot_frame = tk.Frame(self.main) self.validlist = tk.Listbox(self.bot_frame, width=30) self.validlist.pack(side="left") self.scrollbar = tk.Scrollbar(self.bot_frame) self.scrollbar.pack(side="right", fill="y") self.QUIT = tk.Button(self.top_frame, text="QUIT", fg="red", command=self.main.destroy) self.QUIT.pack(side='left') self.bot_frame.pack() tk.mainloop() def showError(self): tk.messagebox.showinfo('You have entered too many letters') def getRackData(self): rack = input(self.rackent.get()) def main(): rack="" gui = application() #dictionary for the scores scores = {"A": 1, "C": 3, "B": 3, "E": 1, "D": 2, "G": 2, "F": 4, "I": 1, "H": 4, "K": 5, "J": 8, "M": 3, "L": 1, "O": 1, "N": 1, "Q": 10, "P": 3, "S": 1, "R": 1, "U": 1, "T": 1, "W": 4, "V": 4, "Y": 4, "X": 8, "Z": 10} #get the rack letters #rack = getRackLetters(gui) #call module to put file into an array rack = getRackLetters(rack,gui) putFileIntoArray(rack, scores) # function to get rack letters def getRackLetters(rack,gui): rack = rack.upper() #call function to verify number of letters entered verify= verifyRackLetters(rack) if verify == True: return rack else: gui.showError() main() #function to verify number of letters entered def verifyRackLetters(rack): if len(rack) <= 8: verify = True else: verify = False return verify #module to put file into an array def putFileIntoArray(rack, scores): words = [] file = open("dict.dat", "r") for line in file: line = line.strip() words.append(line) file.close() #call module to find and create an array of valid words then score them findValidWords(words, scores) # module to find and create an array of valid words then score them def findValidWords(words, rack, scores): valid = [] for word in words: candidate = True rack_letters = list(rack) for letter in word: if letter not in rack_letters: candidate = False else: rack_letters.remove(letter) #score the valid words and append to list if candidate == True: total = 0 for letter in word: total = total + scores[letter] valid.append([total, word]) #call module to sort and print the valid words list with scores scoreValidWords(valid) #module to sort and print the list def scoreValidWords(valid): valid.sort() for entry in valid: score = entry[0] word = entry[1] results.append(str(score) + " " + word) print(results) main() ```