Skip to content

Instantly share code, notes, and snippets.

@evmorov
Created September 3, 2016 21:17
class MineSolver
def safe(board)
@board = board.split("\n").reject(&:empty?).map do |row|
row.chars.map { |field| field == ' ' || field == '?' ? field : field.to_i }
end
set_risks
find_mine while is_there_mine?
safe = []
each_field do |field, x, y|
safe.push([x, y]) if field.eql?(0.0) || field == 's'
end
safe
end
private
def is_there_mine?
each_field do |field|
return true if field.is_a?(Float) && field >= 1.0
end
false
end
def set_risks
each_field do |field, x, y|
set_risks_around(x, y) if field.is_a?(Integer)
end
end
def set_risks_around(x, y)
possible_around = []
around(x, y) do |x_a, y_a|
field = @board[x_a][y_a]
possible_around.push([x_a, y_a]) if field == '?' || field.is_a?(Float)
end
possible_around.each do |pos|
field = @board[pos[0]][pos[1]]
risk = @board[x][y] / possible_around.size.to_f
@board[pos[0]][pos[1]] = (field == '?' ? risk : field + risk)
end
end
def find_mine
high_risk_pos = []
each_field do |field, x, y|
field = @board[x][y]
next unless field.is_a? Float
high_risk_pos = [field, [x, y]] if high_risk_pos.empty? || high_risk_pos[0] < field
end
@board[high_risk_pos[1][0]][high_risk_pos[1][1]] = 'x'
around(high_risk_pos[1][0], high_risk_pos[1][1]) do |x_a, y_a|
next unless @board[x_a][y_a].is_a?(Integer)
@board[x_a][y_a] -= 1
block_fields_around(x_a, y_a) if @board[x_a][y_a].zero?
risk_decrease_around(x_a, y_a)
set_risks_around(x_a, y_a)
end
end
def block_fields_around(x, y)
around(x, y) do |x_a, y_a|
@board[x_a][y_a] = 's' if @board[x_a][y_a].is_a?(Float) || @board[x_a][y_a] == '?'
end
end
def risk_decrease_around(x, y)
around(x, y) do |x_a, y_a|
@board[x_a][y_a] -= 1 if @board[x_a][y_a].is_a?(Float)
end
end
def around(x, y)
(-1..1).each do |x_change|
(-1..1).each do |y_change|
next if x_change.zero? && y_change.zero?
x_around = x + x_change
y_around = y + y_change
next unless in_board?(x_around, y_around)
yield(x_around, y_around)
end
end
end
def in_board?(x, y)
x >= 0 && y >= 0 && x < @board.size && y < @board.first.size
end
def each_field
@board.each_with_index do |row, x|
row.each_with_index do |field, y|
yield(field, x, y)
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment