2022-09-14 14:39:11 +02:00
|
|
|
#!/usr/bin/env ruby
|
2022-09-14 16:17:32 +02:00
|
|
|
# frozen_string_literal: true
|
2022-09-14 15:59:19 +02:00
|
|
|
|
2022-11-22 11:34:19 +01:00
|
|
|
module MineHunt
|
2023-03-15 14:48:25 +01:00
|
|
|
VERSION = '1.1.0'
|
2022-11-22 11:34:19 +01:00
|
|
|
|
2022-09-14 14:39:11 +02:00
|
|
|
class Cell
|
|
|
|
attr_accessor :mine,
|
|
|
|
:open
|
|
|
|
|
|
|
|
def initialize( mine: false, open: false )
|
|
|
|
@mine = mine
|
|
|
|
@open = open
|
|
|
|
end
|
|
|
|
|
|
|
|
def explore
|
|
|
|
@open = true
|
|
|
|
|
|
|
|
@mine
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
class Board
|
|
|
|
attr_reader :width,
|
|
|
|
:height,
|
|
|
|
:field,
|
2022-09-14 16:38:56 +02:00
|
|
|
:number_of_mines,
|
2022-09-14 14:39:11 +02:00
|
|
|
:explorer_x,
|
2022-10-31 22:49:04 +01:00
|
|
|
:explorer_y,
|
|
|
|
:score
|
2022-09-14 14:39:11 +02:00
|
|
|
|
|
|
|
def initialize( number_of_mines = 20, height = 8, width = 16 )
|
|
|
|
@height = height
|
|
|
|
@width = width
|
|
|
|
@explorer_x = 0
|
|
|
|
@explorer_y = 0
|
2022-10-31 22:49:04 +01:00
|
|
|
@score = 1
|
2022-09-14 14:39:11 +02:00
|
|
|
@field = {}
|
2022-09-14 16:38:56 +02:00
|
|
|
@number_of_mines = if number_of_mines.negative? && number_of_mines > ((@height * @width) - 2)
|
|
|
|
20
|
|
|
|
else
|
|
|
|
number_of_mines
|
|
|
|
end
|
2022-09-14 14:39:11 +02:00
|
|
|
|
|
|
|
@width.times do |x|
|
|
|
|
@height.times do |y|
|
|
|
|
@field[[x, y]] = Cell.new( open: x.zero? && y.zero? )
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
placed_mines = 0
|
2022-09-14 16:38:56 +02:00
|
|
|
while placed_mines < @number_of_mines
|
2022-09-14 14:39:11 +02:00
|
|
|
coordinates = [rand( @width ), rand( @height )]
|
|
|
|
next if coordinates == [0, 0]
|
|
|
|
next if @field[ coordinates ].mine
|
|
|
|
|
|
|
|
@field[ coordinates ].mine = true
|
|
|
|
placed_mines += 1
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def update_explorer_location( direction )
|
|
|
|
case direction
|
|
|
|
when 'up'
|
|
|
|
@explorer_y -= 1 if @explorer_y.positive?
|
|
|
|
when 'right'
|
|
|
|
@explorer_x += 1 if @explorer_x < (@width - 1)
|
|
|
|
when 'down'
|
|
|
|
@explorer_y += 1 if @explorer_y < (@height - 1)
|
|
|
|
when 'left'
|
|
|
|
@explorer_x -= 1 if @explorer_x.positive?
|
|
|
|
when 'up-right'
|
|
|
|
if @explorer_x < (@width - 1) && @explorer_y.positive?
|
|
|
|
@explorer_x += 1
|
|
|
|
@explorer_y -= 1
|
|
|
|
end
|
|
|
|
when 'down-right'
|
|
|
|
if @explorer_x < (@width - 1) && @explorer_y < (@height - 1)
|
|
|
|
@explorer_x += 1
|
|
|
|
@explorer_y += 1
|
|
|
|
end
|
|
|
|
when 'down-left'
|
|
|
|
if @explorer_x.positive? && @explorer_y < (@height - 1)
|
|
|
|
@explorer_x -= 1
|
|
|
|
@explorer_y += 1
|
|
|
|
end
|
|
|
|
when 'up-left'
|
|
|
|
if @explorer_x.positive? && @explorer_y.positive?
|
|
|
|
@explorer_x -= 1
|
|
|
|
@explorer_y -= 1
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def move( direction )
|
|
|
|
update_explorer_location( direction )
|
2022-10-31 22:49:04 +01:00
|
|
|
@score += 1 unless @field[[@explorer_x, @explorer_y]].open
|
2022-09-14 14:39:11 +02:00
|
|
|
|
2022-09-14 15:59:19 +02:00
|
|
|
{ dead: @field[[@explorer_x, @explorer_y]].explore,
|
|
|
|
victory: @explorer_x == (@width - 1) && @explorer_y == (@height - 1) }
|
2022-09-14 14:39:11 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
def count_nearby_mines
|
|
|
|
counter = 0
|
2022-09-14 15:59:19 +02:00
|
|
|
|
2022-09-14 14:39:11 +02:00
|
|
|
[@explorer_x - 1, @explorer_x, @explorer_x + 1].each do |x|
|
|
|
|
[@explorer_y - 1, @explorer_y, @explorer_y + 1].each do |y|
|
|
|
|
next if x.negative?
|
|
|
|
next if y.negative?
|
|
|
|
next if x == @width
|
|
|
|
next if y == @height
|
|
|
|
next if x == @explorer_x && y == @explorer_y
|
|
|
|
|
|
|
|
counter += 1 if @field[[x, y]].mine
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
counter
|
|
|
|
end
|
2022-09-14 15:59:19 +02:00
|
|
|
end
|
|
|
|
end
|