๐Ÿงช ๐ŸŽฎ Building a Scrabble Word Finder#

It is amazing how with a few lines of python code you can create some very powerful tools. Here we will implement a scrabble word finder. This tool will help you find the highest scoring word you can make with the letters you have. We will also generate random letters based on the real Scrabble tile frequencies.

This tutorial shows how to create an interactive Scrabble helper that:

  • Finds the highest-scoring word from your letters

  • Generates random letters based on real Scrabble tile frequencies

  • Provides a fun interactive interface

First, letโ€™s import our dependencies:

import itertools
import random
import panel as pn
pn.extension()

๐Ÿ“ Game Data#

Letโ€™s set up our Scrabble scoring system and letter distribution:

# Letter scores
SCRABBLE_SCORES = {
    'a': 1, 'b': 3, 'c': 3, 'd': 2, 'e': 1,
    'f': 4, 'g': 2, 'h': 4, 'i': 1, 'j': 8,
    'k': 5, 'l': 1, 'm': 3, 'n': 1, 'o': 1,
    'p': 3, 'q': 10, 'r': 1, 's': 1, 't': 1,
    'u': 1, 'v': 4, 'w': 4, 'x': 8, 'y': 4,
    'z': 10
}

# Official Scrabble tile distribution
LETTER_DISTRIBUTION = {
    'a': 9, 'b': 2, 'c': 2, 'd': 4, 'e': 12,
    'f': 2, 'g': 3, 'h': 2, 'i': 9, 'j': 1,
    'k': 1, 'l': 4, 'm': 2, 'n': 6, 'o': 8,
    'p': 2, 'q': 1, 'r': 6, 's': 4, 't': 6,
    'u': 4, 'v': 2, 'w': 2, 'x': 1, 'y': 2,
    'z': 1
}

# Let's visualize the letter frequencies
import matplotlib.pyplot as plt

plt.figure(figsize=(15, 5))
plt.bar(LETTER_DISTRIBUTION.keys(), LETTER_DISTRIBUTION.values())
plt.title('Scrabble Tile Distribution')
plt.xlabel('Letter')
plt.ylabel('Number of Tiles')
plt.show()
../../_images/7a94f7c70e1a4df44d1b8e0f0f7602499037e185901c51f13ff8562fdcb03cbe.png

๐ŸŽฒ Core Game Functions#

Now letโ€™s implement our core game logic:

def calculate_score(word):
    """Calculate Scrabble score for a word"""
    return sum(SCRABBLE_SCORES.get(letter, 0) for letter in word)

def generate_words(letters):
    """Generate all possible letter combinations"""
    for length in range(1, len(letters) + 1):
        for combo in itertools.permutations(letters, length):
            yield ''.join(combo)

def generate_random_letters(num_letters=7):
    """Generate random letters based on Scrabble distribution"""
    letter_pool = []
    for letter, count in LETTER_DISTRIBUTION.items():
        letter_pool.extend([letter] * count)
    return ''.join(random.sample(letter_pool, num_letters))

# Test our functions
test_word = "python"
print(f"Score for '{test_word}': {calculate_score(test_word)}")
print(f"Random letters: {generate_random_letters()}")
Score for 'python': 14
Random letters: sraesmz

๐ŸŽฏ Word Finding Logic#

Letโ€™s create a small test dictionary and implement our word finder:

# Small test dictionary
TEST_DICTIONARY = set(['cat', 'hat', 'rat', 'bat', 'at', 'star', 'tars'])

def find_best_scrabble_word(letters, dictionary):
    """Find highest-scoring valid word from letters"""
    best_word = ''
    best_score = 0

    for word in set(generate_words(letters)):
        if word in dictionary:
            score = calculate_score(word)
            if score > best_score:
                best_word = word
                best_score = score

    return best_word, best_score

# Test with sample letters
test_letters = 'stars'
best_word, score = find_best_scrabble_word(test_letters, TEST_DICTIONARY)
print(f"Best word from '{test_letters}': {best_word} (score: {score})")
Best word from 'stars': star (score: 4)

๐ŸŽฎ Interactive Interface#

Finally, letโ€™s create our interactive panel interface:

def create_interface(dictionary):
    """Create interactive Scrabble helper interface"""
    letters_input = pn.widgets.TextInput(name='Enter Letters:', value='')
    random_button = pn.widgets.Button(name='๐ŸŽฒ Random Letters', button_type='primary')
    result_text = pn.widgets.StaticText(name='Result:', value='Type letters or click Random')

    def update_result(event):
        letters = letters_input.value.lower()
        if not letters.isalpha():
            result_text.value = "โš ๏ธ Please enter only letters"
            return
        best_word, score = find_best_scrabble_word(letters, dictionary)
        if best_word:
            result_text.value = f"โœจ Best word: '{best_word}' (Score: {score})"
        else:
            result_text.value = "โŒ No valid words found"

    def generate_random(event):
        letters_input.value = generate_random_letters()
        update_result(None)

    letters_input.param.watch(update_result, 'value')
    random_button.on_click(generate_random)

    return pn.Column(
        pn.pane.Markdown("# ๐ŸŽฏ Scrabble Word Finder"),
        pn.Row(letters_input, random_button),
        result_text
    )


def load_dictionary(file_path):
    """
    Load a dictionary file containing valid Scrabble words.

    Args:
        file_path (str): Path to the dictionary file

    Returns:
        set: Valid Scrabble words

    Note:
        The dictionary should contain one word per line
        Words are converted to lowercase for consistency
    """
    try:
        with open(file_path, "r") as file:
            return set(word.strip().lower() for word in file)
    except FileNotFoundError:
        print(f"Error: Dictionary file not found at '{file_path}'")
        return set()


# Create and display interface
dictionary = load_dictionary("words.txt")
interface = create_interface(dictionary)
interface