Class WordFind
In: lib/wordfind.rb
Parent: Object

Class to generate word-find type puzzles

Methods

add_word   create   get_start   init   insert_word   new   to_html   to_latex   to_s   to_text  

Attributes

puzzle  [R] 
solution  [R] 
words  [R] 

Public Class methods

an array of words, and the following options are allowed:

:size => N:# size of NxN puzzle matrix
:intersect => true|false:# can words intersect (share letters)
:only => ["e","se","ne"]:# compass directions to lay words in
:no => ["w","n"]:# compass directions to not lay words in

[Source]

# File lib/wordfind.rb, line 22
    def initialize(words=[], options={})
        @solution = []
        @words    = []
        @puzzle   = []
        @intersect = options[:intersect] || nil
        @size  = options[:size] || 10
        @lim   = @size - 1
        words.each {|x| add_word(x)}
        if options[:only]
            @directions = @@directions.reject {|key,val|
                not options['only'].include?(key)
            }
        elsif options[:no]
            @directions = @@directions.reject{|key,val|
                options['no'].include?(key)
            }
        else
            @directions = @@directions
        end
    end

Public Instance methods

add a word to the puzzle’s word-list (before calling create), generating warning and dropping the word if it exceeds the Matrix size

[Source]

# File lib/wordfind.rb, line 46
    def add_word(word)
        if word.length > @size
            STDERR.puts "Word too long, dropping <#{word}>"
            return nil
        end
        word.upcase!
        @words << word unless @words.include?(word)
    end

create the puzzle. warnings generated if a word isn’t successfully placed within 50 attempts — word is also dropped

[Source]

# File lib/wordfind.rb, line 58
    def create
        init
        @words.each {|word|
            success = nil
            50.times {
                dirs = @directions.keys
                dir  = dirs[rand(dirs.length)]
                success = insert_word(dir, word)
                break if success
            }
            unless success
                STDERR.puts "Word can't be placed: dropping #{word}"
                @words.delete(word)
            end
        }
        @puzzle = Marshal.load(Marshal.dump(@solution))
        @puzzle.each {|arr|
            arr.collect!{|x| 
                x == '*' ? @@letters[rand(@@letters.length)] : x
            }
        }
    end

no round tuits at the moment

[Source]

# File lib/wordfind.rb, line 98
    def to_html
    end

no round tuits at the moment

[Source]

# File lib/wordfind.rb, line 102
    def to_latex
    end

simple formatted text output of puzzle and solution

[Source]

# File lib/wordfind.rb, line 82
    def to_s
        puzz_str =  "\tWords to Find:\n"
        puzz_str += "\t--------------\n\n"
        words = @words.sort
        until words.empty?
            puzz_str += "\t" + words.slice!(0,3).join("\t") + "\n"
        end
        puzz_str += "\n"
        @puzzle.each {|line|
            puzz_str += "\t" + line.join(' ') + "\n"
        }
        return puzz_str
    end
to_text()

Alias for to_s

Private Instance methods

given a word and direction, pick a suitable starting position

[Source]

# File lib/wordfind.rb, line 107
    def get_start(dir, word)
        len = word.length
        case dir
            when 'n' then [(0..@lim).to_a,((len - 1) .. @lim).to_a]
            when 's' then [(0..@lim).to_a,(0 .. (@lim - len)).to_a]
            when 'e' then [(0..(@lim - len)).to_a,(0..@lim).to_a]
            when 'w' then [((len - 1)..@lim).to_a,(0..@lim).to_a]
            when 'ne' then [(0..(@lim - len)).to_a,((len - 1)..@lim).to_a]
            when 'nw' then [((len - 1)..@lim).to_a,((len - 1)..@lim).to_a]
            when 'se' then [(0..(@lim - len)).to_a,(0..(@lim - len)).to_a]
            when 'sw' then [((len - 1)..@lim).to_a,(0..(@lim - len)).to_a]
        end
    end

initialize solution matrix of "*" characters

[Source]

# File lib/wordfind.rb, line 122
    def init
        for i in (0..@lim)
            @solution[i] = []
            for j in (0..@lim)
                @solution[i] << '*'
            end
        end
    end

insert word into puzzle

[Source]

# File lib/wordfind.rb, line 132
    def insert_word(dir,word)
        ranges = get_start(dir,word)
        return nil if ranges[0].empty? || ranges[1].empty?
        i = ranges[1]
        j = ranges[0]
        i = i[rand(i.length)]
        j = j[rand(j.length)]
        lattice = []
        reject = nil
        word.split(//).each {|letter|
            if @solution[i][j] == '*' || @solution[i][j] == letter
                lattice << @solution[i][j]
                i += @directions[dir][0]
                j += @directions[dir][1]
            else
                reject = 1
                break
            end
        }
        return nil if reject
        i = 0
        word.split(//).each {|letter|
            lattice[i].replace(letter)
            i += 1
        }
        return 1
    end

[Validate]