class Minehunter::Game
Responsible for playing mine hunting game
@api public
Constants
- EXIT_KEYS
The keys to exit game
@api private
Attributes
The terminal cursor clearing and positioning
@api public
Public Class Methods
Create a Game
instance
@param [IO] input
the input stream, defaults to stdin
@param [IO] output
the output stream, defaults to stdout
@param [Hash] env
the environment variables
@param [Integer] width
the number of columns
@param [Integer] height
the number of rows
@param [Integer] mines_limit
the total number of mines
@param [Integer] screen_width
the terminal screen width
@param [Integer] screen_height
the terminal screen height
@param [Pastel] decorator
the decorator for styling
@param [Proc] randomiser
the random number generator
@api public
# File lib/minehunter/game.rb, line 49 def initialize(input: $stdin, output: $stdout, env: {}, width: nil, height: nil, mines_limit: nil, screen_width: nil, screen_height: nil, decorator: DEFAULT_DECORATOR, randomiser: DEFAULT_RANDOMISER) @output = output @width = width @top = (screen_height - height - 4) / 2 @left = (screen_width - width - 4) / 2 @pos_x = (width - 1) / 2 @pos_y = (height - 1) / 2 @decorator = decorator @randomiser = randomiser @box = TTY::Box @cursor = TTY::Cursor @reader = TTY::Reader.new(input: input, output: output, env: env, interrupt: :exit) @grid = Grid.new(width: width, height: height, mines_limit: mines_limit) @intro = Intro @intro_top = (screen_height - @intro.height - 2) / 2 @intro_left = (screen_width - @intro.width - 4) / 2 reset end
Public Instance Methods
Check whether or not the game is finished
@return [Boolean]
@api public
# File lib/minehunter/game.rb, line 90 def finished? @lost || @grid.cleared? end
Place a flag
@api private
# File lib/minehunter/game.rb, line 205 def flag return if finished? @grid.flag(@curr_x, @curr_y) unless finished? end
Quit game
@api private
# File lib/minehunter/game.rb, line 214 def keyctrl_x(*) @output.print cursor.clear_screen @output.print cursor.move_to(0, 0) @stop = true end
Move cursor down
@api private
# File lib/minehunter/game.rb, line 248 def keydown(*) return if finished? @curr_y = @grid.move_down(@curr_y) end
Move cursor left
@api private
# File lib/minehunter/game.rb, line 257 def keyleft(*) return if finished? @curr_x = @grid.move_left(@curr_x) end
Control game movement and actions
@param [TTY::Reader::KeyEvent] event
the keypress event
@api private
# File lib/minehunter/game.rb, line 190 def keypress(event) case event.value.to_sym when :h, :a then keyleft when :l, :d then keyright when :j, :s then keydown when :k, :w then keyup when :f, :g then flag when :r then reset when :q then keyctrl_x end end
Move cursor right
@api private
# File lib/minehunter/game.rb, line 266 def keyright(*) return if finished? @curr_x = @grid.move_right(@curr_x) end
Uncover a field
@api private
# File lib/minehunter/game.rb, line 224 def keyspace(*) return if @grid.flag?(@curr_x, @curr_y) if @first_uncover @grid.fill_with_mines(@curr_x, @curr_y, randomiser: @randomiser) @first_uncover = false end @lost = @grid.uncover(@curr_x, @curr_y) end
Move cursor up
@api private
# File lib/minehunter/game.rb, line 239 def keyup(*) return if finished? @curr_y = @grid.move_up(@curr_y) end
Render grid with current position marker
@api private
# File lib/minehunter/game.rb, line 180 def render_grid @grid.render(@curr_x, @curr_y, decorator: @decorator) end
Render box with grid
@return [String]
@api private
# File lib/minehunter/game.rb, line 149 def render_grid_box @box.frame( render_grid, top: @top + 2, left: @left, padding: [0, 1], border: { top_left: :divider_right, top_right: :divider_left } ) end
Render box with intro
@return [String]
@api private
# File lib/minehunter/game.rb, line 118 def render_intro_box @box.frame( @intro.render, top: @intro_top, left: @intro_left, padding: [0, 1] ) end
Render box with status message
@return [String]
@api private
# File lib/minehunter/game.rb, line 132 def render_status_box @box.frame( status, top: @top, left: @left, width: @width + 4, padding: [0, 1], border: {bottom: false}, align: :center ) end
Reset game
@api public
# File lib/minehunter/game.rb, line 76 def reset @curr_x = @pos_x @curr_y = @pos_y @first_uncover = true @lost = false @stop = false @grid.reset end
Start the game
@api public
# File lib/minehunter/game.rb, line 97 def run @output.print cursor.hide + cursor.clear_screen + render_intro_box pressed_key = @reader.read_keypress keyctrl_x if EXIT_KEYS.include?(pressed_key) @output.print cursor.clear_screen @reader.subscribe(self) until @stop @output.print render_status_box + render_grid_box @reader.read_keypress end ensure @output.print cursor.show end
Status message
@return [String]
@api public
# File lib/minehunter/game.rb, line 167 def status if @lost "GAME OVER" elsif @grid.cleared? "YOU WIN" else "Flags #{@grid.flags_remaining}" end end