class Board

Attributes

flags_remaining[RW]
grid[R]
size[R]

Public Class Methods

new(size = 10) click to toggle source
# File lib/minesweeper.rb, line 7
def initialize(size = 10)
  raise "size out of range!" unless size.between?(8, 25)
  @size = size
  @grid = Array.new(size){ Array.new(size){ Space.new } }

  place_mines
  count_nearby_mines

  #must be after mine placement
  @flags_remaining = mine_count
end

Public Instance Methods

[](index) click to toggle source

rather than just calling board.grid[col] this passes the grid directly through so you can call board[col]

# File lib/minesweeper.rb, line 54
def [](index)
  self.grid[index]
end
endgame_render() click to toggle source

show everything if you lose

# File lib/minesweeper.rb, line 45
def endgame_render
  self.grid.flatten.each {|space| space.visible = true }
  render
end
game_lost?() click to toggle source
# File lib/minesweeper.rb, line 93
def game_lost?
  touched_a_mine? 
end
mark_clear( x, y ) click to toggle source
# File lib/minesweeper.rb, line 69
def mark_clear( x, y )
  return false if self[x][y].visible
  self[x][y].visible = true

  if self[x][y].zero_nearby?

    #mark all of them as well
    adjacent_spaces(x, y).each do |coords|
      adj_x, adj_y = coords[0], coords[1]
      mark_clear(adj_x, adj_y)
    end

  end

  true
end
mine_count() click to toggle source

this took lots of refactoring!!!

# File lib/minesweeper.rb, line 20
def mine_count
  grid.flatten.count { |space| space.mine }
end
num_adjacent_mines(x, y) click to toggle source
# File lib/minesweeper.rb, line 97
def num_adjacent_mines(x, y)
  mine_count = 0

  adjacent_spaces(x, y).each do |coords|
    adj_x, adj_y = coords[0], coords[1]
    mine_count += 1 if self.grid[adj_x][adj_y].mine
  end

  mine_count
end
place_flag( x, y ) click to toggle source
# File lib/minesweeper.rb, line 60
def place_flag( x, y )
  return false if flags_remaining <= 0
  return false if self[x][y].visible

  self[x][y].flagged = true
  self.flags_remaining -= 1
  true
end
render() click to toggle source
# File lib/minesweeper.rb, line 24
def render
  (self.size-1).downto(0) do |y|
    print "#{y}|"
    (0).upto(self.size-1) do |x|
      render_cell(x, y)
      print " "
    end
    puts "|\n"
  end

  print "  "
  print "--" * size
  puts "\n"
  print " "
  0.upto(self.size-1) {|x| print " #{x}"}
  puts "\n"
  puts "Flags remaining: #{flags_remaining}\n"
  nil
end
victory?() click to toggle source

all non-mine spaces are visible

# File lib/minesweeper.rb, line 87
def victory?
  self.grid.flatten.select {|space| !space.mine }.
                    all? {|space| space.visible }
end

Private Instance Methods

adjacent_spaces(x,y) click to toggle source
# File lib/minesweeper.rb, line 149
def adjacent_spaces(x,y)

  coords = []

  (x - 1).upto(x + 1) do |adj_x|
    (y - 1).upto(y + 1) do |adj_y|

      # don't count yourself
      next if ((x == adj_x) && (y == adj_y))

      #if coords are within the bounds of the grid
      if (adj_x >= 0 && adj_y >= 0) && (adj_x < self.size && adj_y < self.size)

        #add them to the list of adjacent coordinates
        coords.push([adj_x, adj_y])
      end
    end
  end

  coords
end
can_clear?( x, y ) click to toggle source

used to decide whether recursive clearing is possible on a space (No mine, not visible yet) AND has 0 nearby mines

# File lib/minesweeper.rb, line 135
def can_clear? ( x, y )
  !self[x][y].visible && 
  !self[x][y].mine && 
  self[x][y].nearby_mines == 0
end
count_nearby_mines() click to toggle source
# File lib/minesweeper.rb, line 141
def count_nearby_mines
  0.upto(self.grid.size - 1) do |x|
    0.upto(self.grid.size - 1) do |y|
      self.grid[x][y].nearby_mines = num_adjacent_mines(x, y)
    end
  end
end
place_mines() click to toggle source
# File lib/minesweeper.rb, line 172
def place_mines

  mines_to_place = [ (self.size - 7)**2, 100].min

  while mines_to_place > 0
    x, y = rand(self.size), rand(self.size)

    unless self.grid[x][y].mine
      self.grid[x][y].mine = true
      mines_to_place -= 1
    end

  end

end
render_cell(x, y) click to toggle source
# File lib/minesweeper.rb, line 111
def render_cell(x, y)
  cell = self.grid[x][y]

  if !cell.visible && cell.flagged
    print "F"
  elsif !cell.visible
    print "_"
  elsif cell.mine
    print "M"
  else
    print cell.nearby_mines
  end
end
touched_a_mine?() click to toggle source

oops. you found a mine

# File lib/minesweeper.rb, line 127
def touched_a_mine?
  self.grid.flatten.any?{ |cell| cell.visible && cell.mine }
end