Class: Upwords::Shape

Inherits:
Object
  • Object
show all
Defined in:
lib/upwords/shape.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(positions = []) ⇒ Shape

Returns a new instance of Shape.



9
10
11
12
# File 'lib/upwords/shape.rb', line 9

def initialize(positions = [])
  @positions = Set.new
  positions.reduce(self) {|shape, (row, col)| shape.add(row, col)}
end

Instance Attribute Details

#positionsObject (readonly)

Returns the value of attribute positions.



7
8
9
# File 'lib/upwords/shape.rb', line 7

def positions
  @positions
end

Instance Method Details

#add(row, col) ⇒ Object Also known as: <<



83
84
85
86
87
88
89
90
# File 'lib/upwords/shape.rb', line 83

def add(row, col)
  if row.is_a?(Integer) && col.is_a?(Integer)
    @positions.add [row, col]
    self
  else
    raise ArgumentError, "[#{row}, #{col}] is not a valid position]"
  end
end

#col_rangeObject



79
80
81
# File 'lib/upwords/shape.rb', line 79

def col_range
  Range.new(*@positions.map {|row, col| col}.minmax)
end

#covering_moves?(board) ⇒ Boolean

Check if move shape completely covers any existing word on the board

Returns:

  • (Boolean)


37
38
39
40
41
# File 'lib/upwords/shape.rb', line 37

def covering_moves?(board)
  (board.word_positions).any? do |word_posns|
    positions >= word_posns
  end
end

#empty?Boolean

Returns:

  • (Boolean)


94
95
96
# File 'lib/upwords/shape.rb', line 94

def empty?
  @positions.empty?
end

#gaps_covered_by?(board) ⇒ Boolean

Check if all empty spaces in the rows and columns spanned by the move shape are covered by a previously-played tile on board For example, if the move shape = [1,1] [1,2] [1,4], then this method returns ‘true’ if the board has a tile at position [1,3] and ‘false’ if it does not.

Returns:

  • (Boolean)


46
47
48
49
50
51
52
# File 'lib/upwords/shape.rb', line 46

def gaps_covered_by?(board)
  row_range.all? do |row|
    col_range.all? do |col|
      @positions.include?([row, col]) || board.nonempty_space?(row, col)
    end
  end
end

#in_middle_square?(board) ⇒ Boolean

Check if at least one position within the move shape is within the middle 2x2 square on the board This check is only performed at the beginning of the game

Returns:

  • (Boolean)


65
66
67
68
69
# File 'lib/upwords/shape.rb', line 65

def in_middle_square?(board)
  board.middle_square.any? do |posn|
    @positions.include?(posn)
  end
end

#include?(row, col) ⇒ Boolean

Returns:

  • (Boolean)


102
103
104
# File 'lib/upwords/shape.rb', line 102

def include? (row, col)
  @positions.include? [row, col]
end

#legal?(board, raise_exception = false) ⇒ Boolean

Check if move creates a legal shape when added to a given board. NOTE: All checks assume that the move in question has not been played on the board yet.

Returns:

  • (Boolean)


16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/upwords/shape.rb', line 16

def legal?(board, raise_exception = false)        
  if board.empty? && !in_middle_square?(board)
    raise IllegalMove, "You must play at least one letter in the middle 2x2 square!" if raise_exception
  elsif board.empty? && (self.size < board.min_word_length)
    raise IllegalMove, "Valid words must be at least #{board.min_word_length} letter(s) long!" if raise_exception
  elsif !straight_line?
    raise IllegalMove, "The letters in your move must be along a single row or column!" if raise_exception
  elsif !gaps_covered_by?(board)
    raise IllegalMove, "The letters in your move must be internally connected!" if raise_exception
  elsif !(board.empty? || touching?(board))
    raise IllegalMove, "At least one letter in your move must be touching a previously played word!" if raise_exception
  elsif covering_moves?(board)  
    raise IllegalMove, "Cannot completely cover up any previously-played words!" if raise_exception
  else
    return true
  end

  return false
end

#row_rangeObject



75
76
77
# File 'lib/upwords/shape.rb', line 75

def row_range
  Range.new(*@positions.map {|row, col| row}.minmax)
end

#sizeObject



98
99
100
# File 'lib/upwords/shape.rb', line 98

def size
  @positions.size
end

#straight_line?Boolean

Returns:

  • (Boolean)


71
72
73
# File 'lib/upwords/shape.rb', line 71

def straight_line?
  row_range.size == 1 || col_range.size == 1
end

#touching?(board) ⇒ Boolean

Check if at least one position within the move shape is adjacent to or overlapping any tile on the board

Returns:

  • (Boolean)


55
56
57
58
59
60
61
# File 'lib/upwords/shape.rb', line 55

def touching?(board)
  @positions.any? do |row, col|
    [[0, 0], [1, 0], [-1, 0], [0, 1], [0, -1]].any? do |dr, dc|
      board.nonempty_space?(row + dr, col + dc)
    end
  end
end