> by Jim Weirich > > Here's a program I've had a lot of fun with and might make a good Ruby > Quiz entry. The program is a animal quiz program. The first thing I thought was "Knowledge Representation" (expert systems and the like). But then, for new animals you will have unanswered older questions, and for old animals you will most definitely not have answers to new questions. So you could ask answers to the player for those as well, but that's getting boring rather soon. If you had the info, you could start with the question that best splits the collection of animals in half; rinse and repeat. Hopefully, you wouldn't have to ask all questions, then. But I don't know how to handle unknown answers for this. Anyone? Put my solution on my webpages (very primitive for now). http://chmeee.dyndns.org/~kero/ruby/quiz/index.html Solution attached at the bottom if you can't read it from there. Funny stuff is in the querying; I know Animal#to_s is rather incomplete. Pointers welcome. +--- Kero ----------------------- kero@chello@nl ---+ | all the meaningless and empty words I spoke | | Promises -- The Cranberries | +--- M38c --- http://httpd.chello.nl/k.vangelder ---+ Animal = Struct.new(:name, :answers) TreeNode = Struct.new(:question, :yes, :no) # left/right has no meaning tree = Animal.new("cat", {}) class Animal def to_s() use_an = ["a", "e", "i", "o"].include? name[0,1] "#{use_an ? "an" : "a"} #{name}" end end def query(str) STDOUT.write "#{str}? "; STDOUT.flush gets end def boolean_query(str) begin STDOUT.write "#{str}? (y/n) "; STDOUT.flush case gets when /^y/i; true when /^n/i; false else raise "ugh" # an exception feels over the top... end rescue puts "please answer with 'y' or 'n'." retry # ...but the keyword "retry" feels very appropriate. end end loop { puts "You think of an animal..." prev, branch = nil, tree answers = {} while branch.kind_of? TreeNode ans = boolean_query branch.question answers[branch.question] = ans prev = branch branch = ans ? branch.yes : branch.no end if boolean_query "Is it #{branch}" puts "I win! Ain't I smart? :P" else puts "I give up. You win!" target = query "What animal were you thinking of" target = Animal.new(target.chomp, answers) puts "I want to learn from my mistake. Please give me" question = query "a question that distinguishes #{target} from #{branch}" question.chomp! question.capitalize! question.slice!(-1) if question[-1,1] == "?" answer = boolean_query "What is the answer to '#{question}?' for #{target}" target.answers[question] = answer pair = (answer ? [target, branch] : [branch, target]) new_node = TreeNode.new(question, *pair) if prev if prev.yes == branch prev.yes = new_node else prev.no = new_node end else tree = new_node end end ans = boolean_query "Do you want to play again" break if not ans } puts "Thanks for playing!"