# A Nested Array to Model a Bingo Board SOLO CHALLENGE

# I spent [6] hours on this challenge.


# Release 0: Pseudocode
# Outline:
# Create a method to generate a letter ( b, i, n, g, o) and a number (1-100)
  #fill in the outline here
    # => Create a method that has an array `bingo` of the letters [B,I,N,G,O], a variable `column_num` that represents a random index from the `bingo` array, and a random integer 1-100 represented by the variable `called_number`. This will return a legible string in the style of a bingo call i.e. "B15"

# Check the called column for the number called.
# If the number is in the column, replace with an 'x'
  #fill in the outline here
    # => Create a method that examines the Bingo board by row.
    # => If the index value of the column `column_num`  equals `called_number`, mark that value "X"

# Display a column to the console
  #fill in the outline here
    # => Transpose `board`, and print the corresponding board[column_num] index.

# Display the board to the console (prettily) - executed this in the refactor
  #fill in the outline here
    # => For each value in the board array, puts the value.
    # => Print a spaced row " B   I   N   G   O  "
    # => Print a spaced row "--------------------"
    # => Print a spaced row of the first array contained in `board` with each value centered in a 5 space area
    # => Print a spaced row of the second array contained in `board` with each value centered in a 5 space area
    # => Print a spaced row of the third array contained in `board` with each value centered in a 5 space area
    # => Print a spaced row of the fourth array contained in `board` with each value centered in a 5 space area
    # => Print a spaced row of the fifth array contained in `board` with each value centered in a 5 space area


# Initial Solution

# class BingoBoard
# attr_accessor :board
# attr_reader :called_letter
# attr_reader :called_number

#   def initialize(board)
#     @bingo_board = board
#   end

#   def bingo_call
#     @bingo = ["B","I","N","G","O"]
#     @column_num = rand(0..4)
#     @called_letter = @bingo[@column_num]
#     @called_number = rand(1..100)
#     puts @called_letter.to_s + " " + @called_number.to_s
#   end

#   def check
#     @bingo_board.each do |board_row|
#         if board_row[@column_num] == @called_number
#           board_row[@column_num]= "X"
#         end
#     end

#     puts
#     print_board
#     puts

#   end


#   def print_board
#     puts "B I N G O "
#     puts "-----------"
#     puts "#{@bingo_board[0][0]} #{@bingo_board[0][1]} #{@bingo_board[0][2]} #{@bingo_board[0][3]} #{@bingo_board[0][4]}"
#     puts "#{@bingo_board[1][0]} #{@bingo_board[1][1]} #{@bingo_board[1][2]} #{@bingo_board[1][3]} #{@bingo_board[1][4]}"
#     puts "#{@bingo_board[2][0]} #{@bingo_board[2][1]} #{@bingo_board[2][2]} #{@bingo_board[2][3]} #{@bingo_board[2][4]}"
#     puts "#{@bingo_board[3][0]} #{@bingo_board[3][1]} #{@bingo_board[3][2]} #{@bingo_board[3][3]} #{@bingo_board[3][4]}"
#     puts "#{@bingo_board[4][0]} #{@bingo_board[4][1]} #{@bingo_board[4][2]} #{@bingo_board[4][3]} #{@bingo_board[4][4]}"
#   end

# end

# Refactored Solution

# class BingoBoard

#   def initialize(board)
#     @bingo_board = board
#   end

#   def bingo_call
#     @bingo = ["B","I","N","G","O"]
#     @column_num = rand(0..4)
#     @called_letter = @bingo[@column_num]
#     @called_number = rand(1..100)
#     puts @called_letter.to_s + " " + @called_number.to_s
#   end

#   def check
#     @bingo_board.each do |board_row|
#         if board_row[@column_num] == @called_number
#           board_row[@column_num]= "X"
#         end
#     end

#     puts
#     print_board
#     puts
#     puts
#     puts
#   end

#   def print_board
#     puts " B    I    N    G    O  "
#     puts "------------------------"
#       @bingo_board.each do |row|
#         row.each do |value|
#           print value.to_s.center(5, " ")
#         end
#         puts
#       end
#   end

# end


#DRIVER CODE GO BELOW THIS LINE

# board = [[47, 44, 71, 8, 88],
#         [22, 69, 75, 65, 73],
#         [83, 85, 97, 89, 57],
#         [25, 31, 96, 68, 51],
#         [75, 70, 54, 80, 83]]

# board = [[1, 2, 3, 2, 1,],
#         [4, 5, 6, 5, 4],
#         [7, 8, 9, 8, 7],
#         [4, 5, 6, 5, 4],
#         [1, 2, 3, 2, 1]]


# test = BingoBoard.new(board)
# 10.times do |x|
#     test.bingo_call
#     test.check
# end


#Reflection
=begin

How difficult was pseudocoding this challenge? What do you think of your pseudocoding style?
Well, pseudocoding was the only way to solve a challenge like this. It took me three iterations of attacking the problem through pseudocode to find a working solution in the actual code. Whiteboarding the idea and visualizing the data flow is what ultimately allowed me to find a solution.

What are the benefits of using a class for this challenge?
Variables can be more easily shared within a class, but also the class describes an object that can have multiple iterations. With a class as complex as this, being able to call an instance makes the program much easier to read.

How can you access coordinates in a nested array?
Coordinates in a 2-dimensional nested array can be accessed first by calling the position in the outer array, and then the position in the inner array.

What methods did you use to access and modify the array?
I used .each to pick the row from the `board` array, and an `if` statement to check the column position within the row `array`. A simple assignment was made to the value of positions matching the called column and value, changin their value to the string "X".

Give an example of a new method you learned while reviewing the Ruby docs. Based on what you see in the docs, what purpose does it serve, and how is it called?
I initially attempted to use .transpose to switch rows for columns to easily compare all B, I, N, G, and O columns against the called column and number. It didn't work out, but I used it in the optional randomized board solution below! I also used the *.center method to beautify the output of the BINGO board (found it previously on p. 232 of Well-Grounded Rubyist, and read up further on the Ruby Docs during this challenge). It serves to position printed output by a number of spaces filled with a space or character, i.e. *.center(spaces,"character")

How did you determine what should be an instance variable versus a local variable?
I used instance variables throughout. There weren't use-appropriate uses of local variables in my approach to this exercise. Methods across the class needed to access variables created in the `initialize` method.

What do you feel is most improved in your refactored solution?
  I improved upon the printed output - in the initial solution, the output was roughly spaced, but formatting collapsed when single-digit values were on the board, or when an "X" was placed on a called value. I'd spent so much time getting my initial solution that I only had remaining time to beautify my output without refactoring my approach to the exercise.

  I instead attempted the bingo board generator optional challenge, and that follows below this reflection. In my refactored solution, I refactored the randomized board generator for readability, and to ensure that unique values for each column range were selected by Ruby, sorting the selected unique random values of each column low to high, in addition to manually placing an "X" on the free space in the center of column "N".

=end





# OPTIONAL Bingo Board Generator

#Initial solution
# class RandomBingoBoard
#   def initialize
#     b = [rand(1..15)] << rand(1..15) << rand(1..15) << rand(1..15) << rand(1..15)
#     i = [rand(16..30)] << rand(16..30) << rand(16..30) << rand(16..30) << rand(16..30)
#     n = [rand(31..45)] << rand(31..45) << "X" << rand(31..45) << rand(31..45)
#     g = [rand(46..60)] << rand(46..60) << rand(46..60) << rand(46..60) << rand(46..60)
#     o = [rand(61..75)] << rand(61..75) << rand(61..75) << rand(61..75) << rand(61..75)
#     @board = [b,i,n,g,o].transpose
#     p @board
#   end

  #   def print_board
  #   puts " B    I    N    G    O  "
  #   puts "------------------------"
  #     @board.each do |row|
  #       row.each do |value|
  #         print value.to_s.center(5, " ")
  #       end
  #       puts
  #     end
  # end
# end

#Refactored Solution

class RandomBingoBoard

  def initialize
    #Sets each column to pull 5 unique values from a range array, sorts ascending
    b = (1..15).to_a.sample(5).sort
    i = (16..30).to_a.sample(5).sort
    n = (31..45).to_a.sample(5).sort
    g = (46..60).to_a.sample(5).sort
    o = (61..75).to_a.sample(5).sort
    n[2] = "X" #Places "free" space in middle of board

    @board = [b,i,n,g,o].transpose
    puts
    p @board
    puts
  end

  def print_board
    puts " B    I    N    G    O  "
    puts "------------------------"
      @board.each do |row|
        row.each do |value|
          print value.to_s.center(5, " ")
        end
        puts
      end
  end

end


test = RandomBingoBoard.new
test.print_board