Boggle in Ruby: Getting Words

Harry Turnbull
5 min readFeb 29, 2020

Previously in this project, I had set up a class that can initialise a game of Boggle, and display the grid of letters to the player.

The project is available on GitHub, so why not check it out and have a game?

An empty notebook, ready for your list of Boggle words.
An empty notebook, ready for your list of Boggle words. Photo by Kelly Sikkema on Unsplash

Today’s task

So, we’ve displayed the grid to players, now the players will start to write down their list of words that they can see in the grid.

Entering words

Let’s write a little bit of code so players can type in their words:

words = []
puts "Type in your words, press enter to submit."
loop do
input = gets.chomp
words.push(input)
end

First we create the words array , then display a message to the player telling them to type in their words. The loop starts, and input is assigned with the gets method that allows players to type in their word and submit it with enter. The chomp method removes the line break that is added when the player presses enter. The input is then added on to the end of the words array with the push method. Then loop starts again, allowing another word.

This loop will never stop though, and that’s not good! Let’s add some way to break out of the loop. The player is typing in words, so a command to “quit” won’t be suitable, what if the player wants to add the word “quit”. We’ll use a “!” instead.

loop do
input = gets.chomp
if input == '!'
break
else
words.push(input)
end
end
puts "Your words are:"
puts words.join(', ')
# =>
Your words are:
here, are, some, words

Now, some if else logic will check if input is “!”break is used to exit the loop. If the input is not “!”, the if block is skipped and the else block is executed instead, adding words to the array as before.

After the loop is broken out of, a message and the list of words the player has entered (separated with commas) will be putsd.

Counting down

Now this is working the player can enter words they find to their hearts content, and when they’re done they can stop, but in Boggle players only have three minutes to enter words. We need a timer:

time = 180
puts time
while time > 0
sleep 1
time -= 1
puts time
end

Here’s a basic timer that counts down 180 seconds. First time is assigned to 180 and time its putsd, then a while loop starts, the sleep method causes the program to wait for 1 second before executing the next line, which decrements time by 1, then puts it. The loop only repeats as long as time more than 0.

Now, there’s a little bit of a problem, at the moment if we run the timer, Ruby will be busy running the timer, and it won’t be able to take words from the player. To do both at the same time we need to use threads. Threads allow Ruby to do work on more than one thing at once:

player_input = Thread.new do  time = 180  timer = Thread.new do
while time > 0
sleep 1
time -= 1
end
puts "\nTime's up!"
player_input.exit
end

loop do
input = gets.chomp
if input == '!'
timer.exit
puts "You quit early with #{time} seconds to go."
break
else
words.push(input)
end
end
end
player_input.joinputs 'Your words are:'
puts words.join(', ')
# player quit early =>
You quit early with 30 seconds to go.
Your words are:
here, are, some, words
# player ran out of time =>
Time's up!
Your words are:
here, are, some, words

Whew! Here’s a timer integrated in. It’s a little complicated so let’s break down what’s happening.

The player_input thread is started and time is set to 180. Then the timer thread is started, nested within the player_input thread, counting down from 180. Once the loop is finished, an escaped new line (\n) and “Time’s up!” are putsd, and the player_input thread is exited with the exit method, the nested timer thread too. This is useful as even though the player will be in a gets input, it will break them out of that, even mid-word.

While the timer is ticking down going on, the loop collects words from the player, and if the player types “!” to quit early, the timer thread is stopped with the exit method, and the player gets a message telling them how much time they had left using string interpolation. (note that in this case, timer thread never got to finish so the “Time’s up!” message isn’t sent).

The player_input.join method causes the main thread to wait until the player_input thread finishes before continuing to execute, otherwise the main thread would head on to display the list of words and end without waiting for the timer to run down.

Finally, the list of words is displayed.

Staying Classy

It’s refactor time! Let’s get this code integrated with the Boggle class:

class Boggle
def initialize
@grid = @@dice.shuffle.map(&:sample).each_slice(4).to_a
@words = []
@time = 180
end
def display
puts row = '+-----+-----+-----+-----+'
@grid.each do |line|
puts "| #{line.map { |c| c.ljust(2) }.join(' | ')} |"
puts row
end
end
def play
puts 'Type in your words, press enter to submit.'
player_input = Thread.new do
timer = Thread.new do
while @time > 0
sleep 1
@time -= 1
end
puts "\nTime's up!"
player_input.exit
end
loop do
input = gets.chomp
if input == '!'
timer.exit
puts "You quit early with #{@time} seconds to go."
break
else
@words.push(input)
end
end
end
player_input.join
puts 'Your words are:'
puts @words.join(', ')
end
@@dice = [
%w[R I F O B X],
%w[I F E H E Y],
%w[D E N O W S],
%w[U T O K N D],
%w[H M S R A O],
%w[L U P E T S],
%w[A C I T O A],
%w[Y L G K U E],
%w[Qu B M J O A],
%w[E H I S P N],
%w[V E T I G N],
%w[B A L I Y T],
%w[E Z A V N D],
%w[R A L E S C],
%w[U W I L R G],
%w[P A C E M D]
]
end
new_game = Boggle.new
new_game.display
new_game.play
# =>
+-----+-----+-----+-----+
| F | U | S | D |
+-----+-----+-----+-----+
| S | K | E | P |
+-----+-----+-----+-----+
| R | O | O | V |
+-----+-----+-----+-----+
| I | Qu | U | H |
+-----+-----+-----+-----+
Type in your words, press enter to submit.
fuse
fused
deus
rook
hope
hopes
Time's up!
Your words are:
fuse, fused, deus, rook, hoop, hopes

There we are, all nicely integrated as a method. Now we don’t even need paper and pens, or a stopwatch to play Boggle! Sweet!

Thanks for reading, see you soon!

--

--

Harry Turnbull

Improviser with Gamez Improv, Improbotics, The Nursery Theatre and Hoopla Impro. Learning to program properly with Makers Academy.