Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save loqi/7639963 to your computer and use it in GitHub Desktop.
Save loqi/7639963 to your computer and use it in GitHub Desktop.
phase 0 unit 2 week 1 boggle class challenge
module Comparable
def not_below(n) self < n ? n : self ; end
def not_above(n) self > n ? n : self ; end
end
class BoggleBoard
attr_reader :width, :height, :vert_range, :horiz_range, :diag_range
def initialize(grid)
@width , @height = grid.first.length , grid.length
raise ArgumentError.new("BoggleBoard needs rectangular array of one-char strings."
) unless ( @width > 0 && @height > 0 &&
grid.all? {|row| row.length == @width &&
row.all? {|cell| cell.kind_of?(String) && cell.length == 1 } } )
@vert_range = 0..(@height-1) ; @horiz_range = 0..(@width-1)
@diag_range = 0..(@width + @height - 2) # Diagonal stripes numbers
@grid = grid ; end
def cell(row, col) @grid[row][col] ; end
def row(row) @grid[row] ; end
def col(col) @grid.map {|row| row[col] } end
def pos_diag(stripe) diag(stripe, false) ; end
def neg_diag(stripe) diag(stripe, true ) ; end
def diag(stripe, neg_slope=false) # Positive Negative
return [] unless @diag_range.include?(stripe) # 0 / 2 3 3 4 5 6
mx_v = @height-1 ; mx_h = @width-1 # 1 / 3 4 2 \ \ \
row = stripe.not_above(mx_v) ; col = stripe - row # 2 / / / 1 \ 3 4
row_col_a = [] ; loop { row_col_a << [row,col] # 3 4 5 6 0 \ 2 3
break unless ( row -= 1 ).between?(0, mx_v) # rising falling
break unless ( col += 1 ).between?(0, mx_h) }
row_col_a = row_col_a.map {|r_c| [ mx_v - r_c.first , r_c.last ]
} if neg_slope
row_col_a.inject([]) {|rval, r_c| row , col = r_c ; rval << cell(row, col) }
end
def create_word(*coords) coords ||= []
coords.map {|r_c| cell(r_c.first, r_c.last) }.join('') ; end
alias_method :get_cell , :cell
alias_method :get_row , :row
alias_method :get_col , :col
end
dice_grid = [ ['b', 'r', 'a', 'e'] ,
['i', 'o', 'd', 't'] ,
['e', 'c', 'l', 'r'] ,
['t', 'a', 'k', 'e'] ]
bb = BoggleBoard.new(dice_grid)
puts bb.vert_range.inject( "Rows of dice from top to bottom:\n"
) {|msg, i| msg << ' ' << bb.row(i).join('') << "\n" }
puts bb.horiz_range.inject("Columns of dice from left to right:\n"
) {|msg, i| msg << ' ' << bb.col(i).join('') << "\n" }
puts bb.diag_range.inject( "Positive-slope diagonals from NW to SE:\n"
) {|msg, i| msg << ' ' << bb.pos_diag(i).join('') << "\n" }
puts bb.diag_range.inject( "Negative-slope diagonals from SW to NE:\n"
) {|msg, i| msg << ' ' << bb.neg_diag(i).join('') << "\n" }
# implement tests for each of the methods here:
p "Tests should print 'true' at every line:"
p bb.create_word( [1,2],[1,1],[2,1],[3,2] ) == 'dock'
p bb.create_word( [3,1],[2,2],[3,3],[2,3],[1,3],[0,3],[1,2] ) == 'alerted'
p bb.create_word( [2,3],[3,3],[2,2],[1,1],[2,1],[3,1],[3,0],[2,0] ) == 'relocate'
p bb.create_word( ) == ''
p bb.get_row(2) == ['e','c','l','r']
p bb.get_col(0) == ['b','i','e','t']
p bb.pos_diag(-1)== []
p bb.pos_diag(0) == ['b']
p bb.pos_diag(3) == ['t','c','d','e']
p bb.pos_diag(6) == ['e']
p bb.pos_diag(7) == []
p bb.neg_diag(0) == ['t']
p bb.neg_diag(3) == ['b','o','l','e']
p bb.neg_diag(6) == ['e']
# create driver test code to retrieve a value at a coordinate here:
p bb.get_cell(0,0) == 'b'
p bb.get_cell(3,3) == 'e'
p bb.get_cell(0,4).nil?
# INCLUDE REFLECTION HERE:
# I decided to make a BoggleBoard class able to create boards of any rectangular
# size. I put a lot of thought into how to make a good diagonal stripe getter.
#
# The OO design keeps all that intricacy away from the calling code. For everything
# below the grid literal, everything just works. That code doesn't have to know
# how to manage the board. It just needs to know how to ask for what it wants.
#
# Perhaps a better constructor would create a grid of requested size and then
# randomly fill in the cells itself, perhaps using simulated letter dice which
# match the physical board game. Maybe for Boggle version 3.
@loqi
Copy link
Author

loqi commented Nov 25, 2013

Rows of dice from top to bottom:
   brae
   iodt
   eclr
   take
Columns of dice from left to right:
   biet
   roca
   adlk
   etre
Positive-slope diagonals from NW to SE:
   b
   ir
   eoa
   tcde
   alt
   kr
   e
Negative-slope diagonals from SW to NE:
   t
   ea
   ick
   bole
   rdr
   at
   e
"Tests should print 'true' at every line:"
true
true
true
true
true
true
true
true
true
true
true
true
true
true
true
true
true

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment