From e6586027238a750768fd6cc75b226eec87086bd2 Mon Sep 17 00:00:00 2001 From: Adam Coffman Date: Wed, 5 Jan 2022 20:17:52 -0600 Subject: [PATCH] initial implementation of FlipFlop in Ruby --- 36_Flip_Flop/ruby/flipflop.rb | 162 ++++++++++++++++++++++++++++++++++ 1 file changed, 162 insertions(+) create mode 100644 36_Flip_Flop/ruby/flipflop.rb diff --git a/36_Flip_Flop/ruby/flipflop.rb b/36_Flip_Flop/ruby/flipflop.rb new file mode 100644 index 00000000..3a65a4c2 --- /dev/null +++ b/36_Flip_Flop/ruby/flipflop.rb @@ -0,0 +1,162 @@ +#A class representing the internal state of a single game of flip flop +# state represents the list of X's (A in the original code) +# guesses represents the number of guesses the user has made (C in the original code) +# seed represents the random seed for an instance of the game (Q in the original code) +Game = Struct.new(:state, :guesses, :seed) do + + #The original BASIC program used 1 indexed arrays while Ruby has 0-indexed arrays. + #We can't use 0 indexed arrays for the flip functions or we'll get divide by zero errors. + #These convenience functions allow us to modify and access internal game state in a 1-indexed fashion + def flip_letter(letter_number) + index = letter_number -1 + if self.state[index] == 'X' + self.state[index] = 'O' + else + self.state[index] = 'X' + end + end + + def letter_at(letter_number) + self.state[letter_number - 1] + end +end + +def print_welcome + puts 'FLIPFLOP'.center(72) + puts 'CREATIVE COMPUTING MORRISTOWN, NEW JERSEY'.center(72) + puts <<~EOS + + THE OBJECT OF THIS PUZZLE IS TO CHANGE THIS: + + X X X X X X X X X X + + TO THIS: + + O O O O O O O O O O + + BY TYPING THE NUMBER CORRESPONDING TO THE POSITION OF THE + LETTER ON SOME NUMBERS, ONE POSITION WILL CHANGE, ON + OTHERS, TWO WILL CHANGE. TO RESET LINE TO ALL X'S, TYPE 0 + (ZERO) AND TO START OVER IN THE MIDDLE OF A GAME, TYPE + 11 (ELEVEN). + EOS +end + +def print_starting_message + puts <<~EOS + + HERE IS THE STARTING LINE OF X'S. + + 1 2 3 4 5 6 7 8 9 10 + X X X X X X X X X X + + EOS +end + +#Create a new game with [X,X,X,X,X,X,X,X,X,X] as the state +#0 as the number of guesses and a random seed between 0 and 1 +def generate_new_game + Game.new(Array.new(10, 'X'), 0, rand()) +end + +#Given a game, an index, and a shuffle function, flip one or more letters +def shuffle_board(game, index, shuffle_function) + n = method(shuffle_function).call(game, index) + + if game.letter_at(n) == "O" + game.flip_letter(n) + if index == n + n = shuffle_board(game, index, shuffle_function) + end + else + game.flip_letter(n) + end + return n +end + +#Shuffle logic copied from original BASIC code +def shuffle_function1(game, index) + r = Math.tan(game.seed + index / game.seed - index) - Math.sin(game.seed / index) + 336 * Math.sin(8 * index) + n = r - r.floor + (10 * n).floor +end + +def shuffle_function2(game, index) + r = 0.592 * (1/ Math.tan(game.seed / index + game.seed)) / Math.sin(index * 2 + game.seed) - Math.cos(index) + n = r - r.floor + (10 * n) +end + +def play_game + print_starting_message + game = generate_new_game + working_index = nil + + loop do + puts "INPUT THE NUMBER" + input = gets.chomp.downcase + + #See if the user input a valid integer, fail otherwise + if numeric_input = Integer(input, exception: false) + + #If 11 is entered, we're done with this version of the game + if numeric_input == 11 + return :restart + end + + if numeric_input > 11 + puts 'ILLEGAL ENTRY--TRY AGAIN.' + next #illegal entries don't count towards your guesses + end + + if working_index == numeric_input + game.flip_letter(numeric_input) + working_index = shuffle_board(game, numeric_input, :shuffle_function2) + #If 0 is entered, we want to reset the state, but not the random seed or number of guesses and keep playing + elsif numeric_input == 0 + game.state = Array.new(10, 'X') + elsif game.letter_at(numeric_input) == "O" + game.flip_letter(numeric_input) + if numeric_input == working_index + working_index = shuffle_board(game, numeric_input, :shuffle_function1) + end + else + game.flip_letter(numeric_input) + working_index = shuffle_board(game, numeric_input, :shuffle_function1) + end + else + puts 'ILLEGAL ENTRY--TRY AGAIN.' + next #illegal entries don't count towards your guesses + end + + game.guesses += 1 + puts '1 2 3 4 5 6 7 8 9 10' + puts game.state.join(' ') + + if game.state.all? { |x| x == 'O' } + if game.guesses > 12 + puts "TRY HARDER NEXT TIME. IT TOOK YOU #{game.guesses} GUESSES." + else + puts "VERY GOOD. YOU GUESSED IT IN ONLY #{game.guesses} GUESSES." + end + #game is complete + return + end + end +end + + + +#Execution starts +print_welcome +loop do + result = play_game + if result == :restart + next + end + + puts 'DO YOU WANT TO TRY ANOTHER PUZZLE' + if gets.chomp.downcase[0] == 'n' + break + end +end