diff --git a/05 Bagels/ruby/README.md b/05 Bagels/ruby/README.md index fb32811e..8e47c0dd 100644 --- a/05 Bagels/ruby/README.md +++ b/05 Bagels/ruby/README.md @@ -1,3 +1,16 @@ +## BAGELS + Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html) -Conversion to [Ruby](https://www.ruby-lang.org/en/) +Conversion to [Ruby](https://www.ruby-lang.org/en/) by [Tom Armitage](https://github.com/infovore) + +## Translator's notes: + +This is a highly imperative port. As such, it's very much, in the spirit of David Ahl's original version, and also highly un-Rubyish. + +A few decisions I made: + +* the main loop is a 'while' loop. Most games are a main loop that runs until it doesn't, and I felt that "while the player wished to keep playing, the game should run" was an appropriate structure. +* lots of puts and gets; that feels appropriate to the Ahl implementation. No clever cli or curses libraries here. +* the number in question, and the player's answer, are stored as numbers. They're only converted into arrays for the purpose of `puts_clue_for` - ie, when comparison is need. The original game stored them as arrays, which made sense, but given the computer says "I have a number in mind", I decided to store what was in its 'mind' as a number. +* the `String#center` method from Ruby 2.5~ sure is handy. diff --git a/05 Bagels/ruby/bagels.rb b/05 Bagels/ruby/bagels.rb new file mode 100644 index 00000000..3a4eb789 --- /dev/null +++ b/05 Bagels/ruby/bagels.rb @@ -0,0 +1,117 @@ +# Bagels +# Number guessing game. +# Original source unknown but suspected to be +# Lawrence Hall of Science, U.C. Berkeley + +def print_instructions + puts + puts 'I am thinking of a three-digit number. Try to guess' + puts 'my number and i will give you clues as follows:' + puts ' PICO - one digit correct but in the wrong position' + puts ' FERMI - one digit correct and in the right position' + puts ' BAGELS - no digits correct' +end + +def generate_target + # pick a three digit number with no repeating numbers. + # gien that, 102-987 is a reasonable starting point! + target = rand(102..987) while target.to_s.split('').uniq.size < 3 + target +end + +def puts_clue_for(guess_number, target_number) + guess_array = guess_number.to_s.split('') + target_array = target_number.to_s.split('') + + clues = [].tap do |clue| + guess_array.each_with_index do |n, i| + if target_array[i] == n + clue << 'FERMI' + elsif target_array.include?(n) + clue << 'PICO' + end + end + end + + # sort clues so that FERMIs come before PICOs, but + # you don't know which response responds to which number + if clues.length > 0 + puts clues.sort.join + else + puts 'BAGELS' + end +end + +player_points = 0 +desire_to_play = true + +puts 'Bagels'.center(72) +puts 'Creative Computing Morristown, New Jersey'.center(72) +5.times { puts } + +puts 'Would you like to the rules? [Y]es or [N]o.' +instructions_request = gets.chomp.downcase + +print_instructions if %w[yes y].include?(instructions_request) + +while desire_to_play + target = generate_target + + 2.times { puts } + puts 'OK. I have a number in mind.' + + guess_count = 0 + guess = 0 + + while (guess != target) && guess_count < 20 + guess_count += 1 + + puts "Guess ##{guess_count}:" + + raw_guess = gets.chomp + + ## if the guess isn't numerical, sound confused + if raw_guess =~ /[^0-9]/ + puts 'What?' + next + end + + ## if the guess is more ore less than three digits, prompt player + if raw_guess.length != 3 + puts 'Try guessing a three digit number' + next + end + + ## if the guess contains duplicate numbers, give player a clue + if raw_guess.split('').uniq.size < 3 + puts 'Oh, I forgot to tell you: the number I have in mind has no two digits the same.' + next + end + + guess = raw_guess.to_i + + if guess != target + puts_clue_for(guess, target) + puts + end + end + + if guess == target + player_points += 1 + + puts 'You got it!!!' + puts + else + puts 'Oh well.' + puts "That's twenty guesses. My number was #{target_number_array.join('')}." + end + + puts + puts 'Would you like to play again? [Y]es or [N]o' + + play_again_request = gets.chomp + desire_to_play = %w[yes y].include?(play_again_request) +end + +puts "A #{player_points} point bagels buff!!" +puts 'Hope you had fun. Bye.'