# rootulp's solution

## to Minesweeper in the Ruby Track

Published at Jul 13 2018 · 0 comments
Instructions
Test suite
Solution

Add the numbers to a minesweeper board.

Minesweeper is a popular game where the user has to find the mines using numeric hints that indicate how many mines are directly adjacent (horizontally, vertically, diagonally) to a square.

In this exercise you have to create some code that counts the number of mines adjacent to a square and transforms boards like this (where `*` indicates a mine):

``````+-----+
| * * |
|  *  |
|  *  |
|     |
+-----+
``````

into this:

``````+-----+
|1*3*1|
|13*31|
| 2*2 |
| 111 |
+-----+
``````

For installation and learning resources, refer to the exercism help page.

For running the tests provided, you will need the Minitest gem. Open a terminal window and run the following command to install minitest:

``````gem install minitest
``````

If you would like color output, you can `require 'minitest/pride'` in the test file, or note the alternative instruction, below, for running the test file.

Run the tests from the exercise directory using the following command:

``````ruby minesweeper_test.rb
``````

To include color from the command line:

``````ruby -r minitest/pride minesweeper_test.rb
``````

## Submitting Incomplete Solutions

It's possible to submit an incomplete solution so you can see how others have completed the exercise.

### minesweeper_test.rb

``````require 'minitest/autorun'
require_relative 'minesweeper'

class MinesweeperTest < Minitest::Test
def test_transform1
inp = ['+------+', '| *  * |', '|  *   |', '|    * |', '|   * *|',
'| *  * |', '|      |', '+------+']
out = ['+------+', '|1*22*1|', '|12*322|', '| 123*2|', '|112*4*|',
'|1*22*2|', '|111111|', '+------+']
assert_equal out, Board.transform(inp)
end

def test_transform2
skip
inp = ['+-----+', '| * * |', '|     |', '|   * |', '|  * *|',
'| * * |', '+-----+']
out = ['+-----+', '|1*2*1|', '|11322|', '| 12*2|', '|12*4*|',
'|1*3*2|', '+-----+']
assert_equal out, Board.transform(inp)
end

def test_transform3
skip
inp = ['+-----+', '| * * |', '+-----+']
out = ['+-----+', '|1*2*1|', '+-----+']
assert_equal out, Board.transform(inp)
end

def test_transform4
skip
inp = ['+-+', '|*|', '| |', '|*|', '| |', '| |', '+-+']
out = ['+-+', '|*|', '|2|', '|*|', '|1|', '| |', '+-+']
assert_equal out, Board.transform(inp)
end

def test_transform5
skip
inp = ['+-+', '|*|', '+-+']
out = ['+-+', '|*|', '+-+']
assert_equal out, Board.transform(inp)
end

def test_transform6
skip
inp = ['+--+', '|**|', '|**|', '+--+']
out = ['+--+', '|**|', '|**|', '+--+']
assert_equal out, Board.transform(inp)
end

def test_transform7
skip
inp = ['+--+', '|**|', '|**|', '+--+']
out = ['+--+', '|**|', '|**|', '+--+']
assert_equal out, Board.transform(inp)
end

def test_transform8
skip
inp = ['+---+', '|***|', '|* *|', '|***|', '+---+']
out = ['+---+', '|***|', '|*8*|', '|***|', '+---+']
assert_equal out, Board.transform(inp)
end

def test_transform9
skip
inp = ['+-----+', '|     |', '|   * |', '|     |', '|     |',
'| *   |', '+-----+']
out = ['+-----+', '|  111|', '|  1*1|', '|  111|', '|111  |',
'|1*1  |', '+-----+']
assert_equal out, Board.transform(inp)
end

def test_different_len
skip
inp = ['+-+', '| |', '|*  |', '|  |', '+-+']
assert_raises(ArgumentError) do
Board.transform(inp)
end
end

def test_faulty_border
skip
inp = ['+-----+', '*   * |', '+-- --+']
assert_raises(ArgumentError) do
Board.transform(inp)
end
end

def test_invalid_char
skip
inp = ['+-----+', '|X  * |', '+-----+']
assert_raises(ArgumentError) do
Board.transform(inp)
end
end
end``````
``````# Board
class Board
def self.transform(input)
Board.new(input).transform
end

def initialize(input)
@grid = input.map(&:chars)
raise ValueError if error?
end

def transform
grid.each_with_index.map do |r, row|
r.each_with_index.map do |square, col|
occupied?(square) ? square : mines_for(row, col)
end.join
end
end

private

def neighbors(row, col)
neighbor_positions.map { |dx, dy| grid[row + dx][col + dy] }
end

def neighbor_positions
(-1..1).to_a.product((-1..1).to_a).reject { |dx, dy| dx == 0 && dy == 0 }
end

def mines_for(row, col)
mines = neighbors(row, col).count { |square| mine?(square) }
mines == 0 ? ' ' : mines.to_s
end

def occupied?(square)
border?(square) || mine?(square)
end

def border?(square)
square == '|' || square == '-' || square == '+'
end

def mine?(square)
square == '*'
end

def error?
invalid_row_length? || invalid_border? || invalid_square?
end

def invalid_border?
invalid_border_row?(grid.first) ||
invalid_border_row?(grid.last) ||
invalid_border_edges?
end

def invalid_border_row?(row)
row.any? { |square| !border?(square) }
end

def invalid_border_edges?
grid.any? { |row| !border?(row.first) || !border?(row.last) }
end

def invalid_row_length?
grid.any? { |row| row.length != grid.first.length }
end

def invalid_square?
grid.join =~ /[^\s*|+-]/
end
end

class ValueError < StandardError
end``````