Class: Mosaic

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

Constant Summary collapse

DuplicateTile =
Class.new(RuntimeError)
DRAW_CHARS =
%[!@#\$%^&*_=+\/\:;'.~abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ].split('')

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(rows, cols) ⇒ Mosaic

Returns a new instance of Mosaic.



6
7
8
9
10
# File 'lib/mosaic.rb', line 6

def initialize(rows, cols)
  @rows, @cols = rows, cols
  @grid = Array.new(@rows) { Array.new(@cols) {:empty} }
  @tiles = []
end

Instance Attribute Details

#colsObject (readonly)

Returns the value of attribute cols.



2
3
4
# File 'lib/mosaic.rb', line 2

def cols
  @cols
end

#gridObject (readonly)

Returns the value of attribute grid.



2
3
4
# File 'lib/mosaic.rb', line 2

def grid
  @grid
end

#rowsObject (readonly)

Returns the value of attribute rows.



2
3
4
# File 'lib/mosaic.rb', line 2

def rows
  @rows
end

#tilesObject (readonly)

Returns the value of attribute tiles.



2
3
4
# File 'lib/mosaic.rb', line 2

def tiles
  @tiles
end

Instance Method Details

#areaObject



12
13
14
# File 'lib/mosaic.rb', line 12

def area
  @rows * @cols
end

#available?(row, col) ⇒ Boolean

Returns:

  • (Boolean)


26
27
28
# File 'lib/mosaic.rb', line 26

def available?(row, col)
  @grid[row] && @grid[row][col] == :empty
end

#available_areaObject



16
17
18
19
20
21
22
23
24
# File 'lib/mosaic.rb', line 16

def available_area
  count = 0
  (0...@rows).each do |row|
    (0...@cols).each do |col|
      count += 1 if available?(row, col)
    end
  end
  count
end

#can_place?(tile, row, col) ⇒ Boolean

Returns:

  • (Boolean)


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

def can_place?(tile, row, col)
  (row...(row + tile.rows)).each do |r|
    (col...(col + tile.cols)).each do |c|
      return false unless available?(r, c)
    end
  end
  true
end

#covered_areaObject



30
31
32
# File 'lib/mosaic.rb', line 30

def covered_area
  area - available_area
end

#drawObject



35
36
37
38
39
40
41
42
43
44
# File 'lib/mosaic.rb', line 35

def draw
  charmap = Hash[@tiles.zip(DRAW_CHARS.first(@tiles.size))]
  charmap[:empty] = ' '
  horizontal = '-'*(@cols + 2)
  puts horizontal
  puts(@grid.map do |row|
    "|#{row.map{|tile| charmap[tile]}.join}|"
  end.join("\n"))
  puts horizontal
end

#generate!Object



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/mosaic.rb', line 55

def generate!
  candidates = Tile.rand_covering(area)
  until candidates.empty? || candidates.all?{|tile| tile.is_a?(Tile::Small) }
    tile = candidates.shift
    placed = false
    5.times {
      row, col = random_location(tile)
      placed = place!(tile, row, col)
      break if placed
    }
    candidates.concat tile.shatter unless placed
  end
  # Fill in missed spaces
  (0...@rows).each do |row|
    (0...@cols).each do |col|
      place!(Tile::Small.new, row, col) if available?(row, col)
    end
  end
  true
end

#has_tile?(tile) ⇒ Boolean

Returns:

  • (Boolean)


76
77
78
# File 'lib/mosaic.rb', line 76

def has_tile?(tile)
  !!@tiles.find {|t| t.equal? tile}
end

#place!(tile, row, col) ⇒ Object

Raises:



80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/mosaic.rb', line 80

def place!(tile, row, col)
  raise DuplicateTile if has_tile?(tile)
  return false unless can_place?(tile, row, col)
  @tiles << tile
  tile.place!(self, row, col)
  (row...(row + tile.rows)).each do |r|
    (col...(col + tile.cols)).each do |c|
      @grid[r][c] = tile
    end
  end
  true
end

#random_location(tile) ⇒ Object



93
94
95
# File 'lib/mosaic.rb', line 93

def random_location(tile)
  [rand(rows - tile.rows + 1), rand(cols - tile.cols + 1)]
end

#space_available?Boolean

Returns:

  • (Boolean)


97
98
99
# File 'lib/mosaic.rb', line 97

def space_available?
  covered_area < area
end