My game will play almost like the one you can play at yahoo without score. Has
cheating and giving-up commands and draws possible solutions on the screen.
Run it with wordblender.rb <dictfile>.
martin
# wordblender.rb
#
# Usage: wordblender.rb [dictfile]
#
class String
# Checks if string can be build out of these characters.
#
# "hello".build_outof?("llohe") => true
# "world".build_outof?("dlrowl") => true
def build_outof?(other)
return false if self.length > other.length
o = other.clone
self.each_byte do |c|
return false unless o.include?(c.chr)
o[o.index(c.chr)] = 0
end
true
end
# Shuffle a word.
#
# "hello".shuffle => "oellh"
def shuffle
return self.scan(/./).sort_by{rand}.to_s
end
end
class WordBlenderGame
attr_reader :words
# limits for words for the game
MINCHARACTERS = 3
MAXCHARACTERS = 6
# time limit per game
TIME_PER_GAME = 90
# how to display the board
DISPLAY_COLUMNS = 5
# read the dictionary from a file.
# we also keep words with length of MAXCHARACTERS to find
# good initial letters quickly.
def initialize(dictionary)
@words, @maxwords = [], []
File.open(dictionary).each do |line|
l = line.strip.downcase
@words << l if (l.length >= MINCHARACTERS && l.length <= MAXCHARACTERS)
@maxwords << l if l.length == MAXCHARACTERS
end
end
# this generates a bunch of letters to play with and looks up words
# that can be build by them from the dictionary ("candidates").
def prepare_game()
@letters = @maxwords[rand(@maxwords.size-1)].shuffle
@candidates = []
@words.each { |w| @candidates << w if w.build_outof?(@letters) }
@candidates = @candidates.uniq # this fixed duplicated entries
@candidates = @candidates.sort {|x,y| x.length <=> y.length }
@found_candidates = @candidates.collect { false }
end
#
# This is to display the candidates to the screen. Draws it into columns
# and returns a string.
#
def get_board(solution=false, title="Words to find")
result = "" ; i = 0
sempty = ' '*(DISPLAY_COLUMNS*(MAXCHARACTERS+2))
s = String.new(sempty)
result << title << ":\n"
@found_candidates.each_index do |idx|
f = @found_candidates[idx] || solution
s[i.modulo(DISPLAY_COLUMNS)*(MAXCHARACTERS+2)] =
f ? "[#{@candidates[idx]}]" : "["+(' '*@candidates[idx].length)+"]"
if i.modulo(DISPLAY_COLUMNS) == DISPLAY_COLUMNS-1 then
result << (s + "\n")
s = String.new(sempty)
end
i+=1
end
result << s if s.include?('[')
result << "\n"
end
# This plays one round of the game, returns true if won
def play
self.prepare_game
message = "Press RETURN to shuffle the letters, '!' to give up, '?' to
cheat."
# start the time.
@time = TIME_PER_GAME
timer = Thread.new { while true do @time-=1; sleep 1 end }
# game loop
while @found_candidates.include?(false) do
# print board and other stuff
puts get_board
puts
puts "Time: " + @time.to_s
puts "Msg: " + message if message != ''
puts "Use: " + @letters
print "Try: "
# get user's guess and handle it
$stdout.flush
s = STDIN.gets.downcase.strip
if @time <= 0 then
puts "Time's up!"
break
end
if s == "" then
@letters = @letters.shuffle
message = "Letters shuffled!"
next
end
break if s == '!'
if s == '?' then
puts get_board(true)
message = "Cheater!"
next
end
if !s.build_outof?(@letters) then
message = "Invalid word!"
next
end
if @candidates.include?(s) then
@found_candidates[@candidates.index(s)] = true
message = "#{s} Found!"
else
message = "#{s} not listed!"
end
end
Thread.kill(timer)
# print solution
puts get_board(true, "Solution is")
# Check if player found a word with all characters
@found_candidates.each_index do |idx|
return true if @found_candidates[idx] && @candidates[idx].length ==
MAXCHARACTERS
end
false
end
end
print "Loading game...";$stdout.flush
game = WordBlenderGame.new(ARGV[1] || '/usr/share/dict/words')
puts "#{game.words.size} words found."
while game.play do
puts "You won, press any key to play next round."
gets
end
puts "Game over!"
On Friday 05 January 2007 13:05, Ruby Quiz wrote:
> The three rules of Ruby Quiz:
>
> 1. Please do not post any solutions or spoiler discussion for this quiz
> until 48 hours have passed from the time on this message.
>
> 2. Support Ruby Quiz by submitting ideas as often as you can:
>
> http://www.rubyquiz.com/
>
> 3. Enjoy!
>
> Suggestion: A [QUIZ] in the subject of emails about the problem helps
> everyone on Ruby Talk follow the discussion. Please reply to the original
> quiz message, if you can.
>
> -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
>=-=-=
>
> by Ben Bleything
>
> This is a riff on the Jumble puzzle found in many (US) newspapers. More
> specifically, it's based on the game TextTwist[1], made by GameHouse[2] and
> published in various places around the web.
>
> The mechanic of TextTwist is simple. The player is given six letters and is
> tasked with unscrambling those letters into as many words as possible. If
> the player can use all six letters in a word, they proceed to the next
> round.
>
> Your task is to build the back-end engine to run a TextTwist clone.
> Effectively, this means that you must generate a list of three- to
> six-letter words that can all be constructed from the same six letters.
> This list must contain at least one six-letter word.
>
> Bonus points for building a completely functional game!
>
> [1]: http://games.yahoo.com/games/texttwist.html (just one example, java)
> [2]: http://www.gamehouse.com/