ðŸŽ‰ Exercism Research is now launched. Help Exercism, help science and have some fun at research.exercism.io ðŸŽ‰

# JaeHyoLee's solution

## to Minesweeper in the Lua 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 |
+-----+
``````

## Running the tests

To run the tests, run the command `busted` from within the exercise directory.

## Further information

For more detailed information about the Lua track, including how to get help if you're having trouble, please visit the exercism.io Lua language page.

## Submitting Incomplete Solutions

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

### minesweeper_spec.lua

``````local minesweeper = require('minesweeper')

describe('minesweeper', function()
it('should be able to transform a 1x1 board with a single mine', function()
local input = {
'*-*',
'|*|',
'*-*'
}
local expected = {
'*-*',
'|*|',
'*-*'
}
assert.same(expected, minesweeper.transform(input))
end)

it('should be able to transform a board with no mines', function()
local input = {
'*---*',
'|   |',
'|   |',
'|   |',
'*---*'
}
local expected = {
'*---*',
'|   |',
'|   |',
'|   |',
'*---*'
}
assert.same(expected, minesweeper.transform(input))
end)

it('should be able to transform a small board with a single mine', function()
local input = {
'*---*',
'|   |',
'| * |',
'|   |',
'*---*'
}
local expected = {
'*---*',
'|111|',
'|1*1|',
'|111|',
'*---*'
}
assert.same(expected, minesweeper.transform(input))
end)

it('should be able to transform a small board with multiple mines', function()
local input = {
'*---*',
'|   |',
'|** |',
'|   |',
'*---*'
}
local expected = {
'*---*',
'|221|',
'|**1|',
'|221|',
'*---*'
}
assert.same(expected, minesweeper.transform(input))
end)

it('should be able to transform a larger board with multiple mines', function()
local input = {
'+------+',
'| *  * |',
'|  *   |',
'|    * |',
'|   * *|',
'| *  * |',
'|      |',
'+------+'
}
local expected = {
'+------+',
'|1*22*1|',
'|12*322|',
'| 123*2|',
'|112*4*|',
'|1*22*2|',
'|111111|',
'+------+'
}
assert.same(expected, minesweeper.transform(input))
end)

it('should be able to transform a board that is not square', function()
local input = {
'*---*',
'|   |',
'|** |',
'*---*'
}
local expected = {
'*---*',
'|221|',
'|**1|',
'*---*'
}
assert.same(expected, minesweeper.transform(input))
end)

it('should assert that the board is a rectangle', function()
local input = {
'*---*',
'|  |',
'| * |',
'*---*'
}
assert.has_error(function()
minesweeper.transform(input)
end)
end)

it('should assert that the input contains only space and asterisk characters on the board', function()
local input = {
'*---*',
'|   |',
'| X |',
'*---*'
}
assert.has_error(function()
minesweeper.transform(input)
end)
end)
end)``````
``````local function increase_element(e)
if e == ' ' then e = 1
elseif nil ~= tonumber(e) then e = tonumber(e) + 1 end
return e
end

local function increase_neighbors(prevRow, currentRow, nextRow, j)
prevRow[j-1] = increase_element(prevRow[j-1])
prevRow[j] = increase_element(prevRow[j])
prevRow[j+1] = increase_element(prevRow[j+1])

currentRow[j-1] = increase_element(currentRow[j-1])
currentRow[j+1] = increase_element(currentRow[j+1])

nextRow[j-1] = increase_element(nextRow[j-1])
nextRow[j] = increase_element(nextRow[j])
nextRow[j+1] = increase_element(nextRow[j+1])
end

local function transform(input)

local output = {}
local width = #input[1]

for i= 2, #input-1 do
if width ~= #input[i] then assert(false, 'wrong!') end

local prevRow = {}
local currentRow = {}
local nextRow = {}

for w in string.gmatch(output[i-1] or input[i-1], '.') do table.insert(prevRow, w) end
for w in string.gmatch(output[i] or input[i], '.') do table.insert(currentRow, w) end
for w in string.gmatch(output[i+1] or input[i+1], '.') do table.insert(nextRow, w) end

for j = 2, width - 1 do
if currentRow[j] == '*' then increase_neighbors(prevRow, currentRow, nextRow, j)
elseif currentRow[j] ~= ' ' and tonumber(currentRow[j]) == nil then assert(false, 'wrong character!') end
end
output[i-1] = table.concat(prevRow)
output[i] = table.concat(currentRow)
output[i+1] = table.concat(nextRow)
end
return output
end

return {
transform = transform
}``````