minesweeper-console 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.coveralls.yml +1 -0
- data/.gitignore +23 -0
- data/.travis.yml +4 -0
- data/Gemfile +4 -0
- data/Guardfile +36 -0
- data/LICENSE.txt +22 -0
- data/README.md +31 -0
- data/Rakefile +11 -0
- data/bin/minesweeper +17 -0
- data/lib/minesweeper/console.rb +4 -0
- data/lib/minesweeper/console/game_loop.rb +58 -0
- data/lib/minesweeper/console/parser/command_parser.rb +47 -0
- data/lib/minesweeper/console/parser/flag_command.rb +18 -0
- data/lib/minesweeper/console/parser/invalid_command_parameters_error.rb +9 -0
- data/lib/minesweeper/console/parser/invalid_input_error.rb +11 -0
- data/lib/minesweeper/console/parser/null_command.rb +14 -0
- data/lib/minesweeper/console/parser/reveal_command.rb +18 -0
- data/lib/minesweeper/console/parser/unflag_command.rb +18 -0
- data/lib/minesweeper/console/parser/unsupported_command_error.rb +9 -0
- data/lib/minesweeper/console/prettyprinter/header_printer.rb +32 -0
- data/lib/minesweeper/console/prettyprinter/minefield_pretty_printer.rb +47 -0
- data/lib/minesweeper/console/prettyprinter/row_printer.rb +41 -0
- data/lib/minesweeper/console/prettyprinter/theme/default_theme.rb +38 -0
- data/lib/minesweeper/console/prettyprinter/theme/null_theme.rb +25 -0
- data/lib/minesweeper/console/version.rb +5 -0
- data/minesweeper-console.gemspec +31 -0
- data/test/minesweeper/console/parser/command_parser_test.rb +59 -0
- data/test/minesweeper/console/parser/flag_command_test.rb +24 -0
- data/test/minesweeper/console/parser/minefield_spy.rb +26 -0
- data/test/minesweeper/console/parser/null_command_test.rb +19 -0
- data/test/minesweeper/console/parser/reveal_command_test.rb +24 -0
- data/test/minesweeper/console/parser/unflag_command_test.rb +24 -0
- data/test/minesweeper/console/prettyprinter/header_printer_test.rb +62 -0
- data/test/minesweeper/console/prettyprinter/minefield_pretty_printer_test.rb +42 -0
- data/test/minesweeper/console/prettyprinter/row_printer_test.rb +60 -0
- data/test/minesweeper/console/prettyprinter/theme/default_theme_test.rb +40 -0
- data/test/minesweeper/console/prettyprinter/theme/null_theme_test.rb +30 -0
- data/test/test_helper.rb +4 -0
- metadata +221 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 239fd63509b9da5143a0824db67bcf5b69054d6d
|
4
|
+
data.tar.gz: 132a852bac982542d6a17ad15b816cfe8c278000
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b01640dc5dfce28e72330a7a8250505918595c7a91d320a013752f957308c80d0944c751468c054f5e03cf2c870a572d38e54d5c7b92f0703448e0b1efda6b3d
|
7
|
+
data.tar.gz: e7fc80dfeecda6f82856c2601bddbe9f5f1b9742080d46a50a71385b2dd0daa137175e1e790d5fe7f5036d426542af3e3a995599dd3139b8742bd0db32d96f4e
|
data/.coveralls.yml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
service_name: travis-ci
|
data/.gitignore
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
/.bundle/
|
2
|
+
/.yardoc
|
3
|
+
/Gemfile.lock
|
4
|
+
/_yardoc/
|
5
|
+
/coverage/
|
6
|
+
/doc/
|
7
|
+
/pkg/
|
8
|
+
/spec/reports/
|
9
|
+
/tmp/
|
10
|
+
*.bundle
|
11
|
+
*.so
|
12
|
+
*.o
|
13
|
+
*.a
|
14
|
+
mkmf.log
|
15
|
+
*.gem
|
16
|
+
.idea/
|
17
|
+
.rakeTasks
|
18
|
+
*.iml
|
19
|
+
<<<<<<< HEAD
|
20
|
+
tags
|
21
|
+
gems.tags
|
22
|
+
*.swp
|
23
|
+
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Guardfile
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# A sample Guardfile
|
2
|
+
# More info at https://github.com/guard/guard#readme
|
3
|
+
|
4
|
+
## Uncomment and set this to only include directories you want to watch
|
5
|
+
# directories %w(app lib config test spec features)
|
6
|
+
|
7
|
+
## Uncomment to clear the screen before every task
|
8
|
+
clearing :on
|
9
|
+
|
10
|
+
## Guard internally checks for changes in the Guardfile and exits.
|
11
|
+
## If you want Guard to automatically start up again, run guard in a
|
12
|
+
## shell loop, e.g.:
|
13
|
+
##
|
14
|
+
## $ while bundle exec guard; do echo "Restarting Guard..."; done
|
15
|
+
##
|
16
|
+
## Note: if you are using the `directories` clause above and you are not
|
17
|
+
## watching the project directory ('.'), then you will want to move
|
18
|
+
## the Guardfile to a watched dir and symlink it back, e.g.
|
19
|
+
#
|
20
|
+
# $ mkdir config
|
21
|
+
# $ mv Guardfile config/
|
22
|
+
# $ ln -s config/Guardfile .
|
23
|
+
#
|
24
|
+
# and, you'll have to watch "config/Guardfile" instead of "Guardfile"
|
25
|
+
|
26
|
+
guard :test do
|
27
|
+
watch(%r{^test/.+_test\.rb$})
|
28
|
+
watch('test/test_helper.rb') { 'test' }
|
29
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "test/#{m[1]}_test.rb" }
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
guard 'ctags-bundler', :src_path => ["lib", "test"] do
|
34
|
+
watch(/^(lib|test)\/.*\.rb$/)
|
35
|
+
watch('Gemfile.lock')
|
36
|
+
end
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2015 Sébastien Varlet
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# Minesweeper::Console
|
2
|
+
|
3
|
+
TODO: Write a gem description
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'minesweeper-console'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install minesweeper-console
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
TODO: Write usage instructions here
|
24
|
+
|
25
|
+
## Contributing
|
26
|
+
|
27
|
+
1. Fork it ( https://github.com/[my-github-username]/minesweeper-console/fork )
|
28
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
29
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
30
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
31
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
data/bin/minesweeper
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'minesweeper/console'
|
4
|
+
|
5
|
+
args = ARGV.dup
|
6
|
+
begin
|
7
|
+
row_count = args.shift.strip.to_i
|
8
|
+
rescue
|
9
|
+
puts "This command requires one argument to set the size of the minefield."
|
10
|
+
end
|
11
|
+
|
12
|
+
trap('INT') do
|
13
|
+
puts 'Bye bye !'
|
14
|
+
exit
|
15
|
+
end
|
16
|
+
Minesweeper::Console::GameLoop.new(row_count).start
|
17
|
+
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'readline'
|
2
|
+
require 'minesweeper/core'
|
3
|
+
require 'rainbow'
|
4
|
+
require_relative 'prettyprinter/minefield_pretty_printer'
|
5
|
+
require_relative 'prettyprinter/theme/default_theme'
|
6
|
+
require_relative 'parser/command_parser'
|
7
|
+
require_relative 'parser/unsupported_command_error'
|
8
|
+
require_relative 'parser/invalid_command_parameters_error'
|
9
|
+
|
10
|
+
module Minesweeper
|
11
|
+
module Console
|
12
|
+
class GameLoop
|
13
|
+
PROMPT = "(R)eveal, (F)lag, (U)nflag <x> <y>\n>"
|
14
|
+
def initialize(size)
|
15
|
+
@row_count = size
|
16
|
+
@minefield = Minefield.new(@row_count)
|
17
|
+
@pretty_printer = Console::PrettyPrinter::MinefieldPrettyPrinter.new(@minefield, Console::PrettyPrinter::Theme::DefaultTheme.new(Rainbow.new))
|
18
|
+
@command_parser = Console::Parser::CommandParser.new(@minefield)
|
19
|
+
mine_generator = Explosives::MineCoordinatesFactory.new(Random.new)
|
20
|
+
@mine_layer = Explosives::MineLayer.new(@minefield, mine_generator)
|
21
|
+
end
|
22
|
+
|
23
|
+
def start
|
24
|
+
@mine_layer.lay(@row_count)
|
25
|
+
loop do
|
26
|
+
begin
|
27
|
+
puts @pretty_printer.print
|
28
|
+
user_input = Readline.readline(PROMPT, true)
|
29
|
+
@command_parser.parse(user_input).execute
|
30
|
+
rescue RangeError => e
|
31
|
+
print_error('Please type coordinates within the minefield range.')
|
32
|
+
rescue Parser::UnsupportedCommandError, Parser::InvalidCommandParametersError => e
|
33
|
+
print_error(e.message)
|
34
|
+
rescue Minesweeper::Explosives::ExplosionError => e
|
35
|
+
print_error(e.message)
|
36
|
+
exit
|
37
|
+
rescue MinefieldSolvedError
|
38
|
+
print_victory
|
39
|
+
exit
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def print_error(message)
|
45
|
+
wrap_with_pretty_lines Rainbow(message).yellow.bright
|
46
|
+
end
|
47
|
+
|
48
|
+
def wrap_with_pretty_lines(message)
|
49
|
+
puts '-' * 79, message, '-' * 79
|
50
|
+
end
|
51
|
+
|
52
|
+
def print_victory
|
53
|
+
wrap_with_pretty_lines Rainbow('Congratulations! You flagged all mines.').green.bright
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require_relative 'invalid_command_parameters_error'
|
2
|
+
require_relative 'unsupported_command_error'
|
3
|
+
require_relative 'null_command'
|
4
|
+
require_relative 'reveal_command'
|
5
|
+
require_relative 'flag_command'
|
6
|
+
require_relative 'unflag_command'
|
7
|
+
|
8
|
+
module Minesweeper
|
9
|
+
module Console
|
10
|
+
module Parser
|
11
|
+
class CommandParser
|
12
|
+
def initialize(a_minefield)
|
13
|
+
raise ArgumentError if a_minefield.nil?
|
14
|
+
@minefield = a_minefield
|
15
|
+
end
|
16
|
+
|
17
|
+
def parse(user_input)
|
18
|
+
if user_input.nil? || user_input =~ /^\s*$/
|
19
|
+
return NullCommand.new(@minefield)
|
20
|
+
end
|
21
|
+
validate_user_input(user_input)
|
22
|
+
tokens = user_input.split(/\s+/)
|
23
|
+
case tokens[0].upcase
|
24
|
+
when 'R', 'REVEAL'
|
25
|
+
RevealCommand.new(@minefield, *tokens[1,2].map(&:to_i))
|
26
|
+
when 'F', 'FLAG'
|
27
|
+
FlagCommand.new(@minefield, *tokens[1,2].map(&:to_i))
|
28
|
+
when 'U', 'UNFLAG'
|
29
|
+
UnflagCommand.new(@minefield, *tokens[1,2].map(&:to_i))
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def validate_user_input(user_input)
|
34
|
+
if user_input !~ /^[RUFruf] .*$/
|
35
|
+
raise UnsupportedCommandError, 'Supported commands are r,u,f,R,U,F.'
|
36
|
+
end
|
37
|
+
if user_input !~ /^.*\d+ \d+$/
|
38
|
+
raise InvalidCommandParametersError, 'A command must be followed by two integers.'
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
private :validate_user_input
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Minesweeper
|
2
|
+
module Console
|
3
|
+
module Parser
|
4
|
+
class FlagCommand
|
5
|
+
def initialize(a_minefield, x, y)
|
6
|
+
@minefield = a_minefield
|
7
|
+
@row_index = x
|
8
|
+
@column_index = y
|
9
|
+
end
|
10
|
+
|
11
|
+
def execute
|
12
|
+
@minefield.flag_at(@row_index, @column_index)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Minesweeper
|
2
|
+
module Console
|
3
|
+
module Parser
|
4
|
+
class RevealCommand
|
5
|
+
def initialize(a_minefield, x, y)
|
6
|
+
@minefield = a_minefield
|
7
|
+
@row_index = x
|
8
|
+
@column_index = y
|
9
|
+
end
|
10
|
+
|
11
|
+
def execute
|
12
|
+
@minefield.reveal_at(@row_index, @column_index)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Minesweeper
|
2
|
+
module Console
|
3
|
+
module Parser
|
4
|
+
class UnflagCommand
|
5
|
+
def initialize(a_minefield, x, y)
|
6
|
+
@minefield = a_minefield
|
7
|
+
@row_index = x
|
8
|
+
@column_index = y
|
9
|
+
end
|
10
|
+
|
11
|
+
def execute
|
12
|
+
@minefield.unflag_at(@row_index, @column_index)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Minesweeper
|
2
|
+
module Console
|
3
|
+
module PrettyPrinter
|
4
|
+
class HeaderPrinter
|
5
|
+
def initialize(separator, theme)
|
6
|
+
raise ArgumentError if separator.nil? || theme.nil?
|
7
|
+
@separator = separator
|
8
|
+
@theme = theme
|
9
|
+
end
|
10
|
+
|
11
|
+
def print(number_of_columns)
|
12
|
+
raise ArgumentError if number_of_columns <= 0
|
13
|
+
column_width = compute_column_width_for(number_of_columns)
|
14
|
+
result = ' ' * column_width
|
15
|
+
result << @theme.colorize_separator(@separator)
|
16
|
+
number_of_columns.times do |i|
|
17
|
+
column_header = @theme.colorize_header(i.to_s)
|
18
|
+
column_header.prepend(' ' * (column_width - i.to_s.length))
|
19
|
+
result << column_header
|
20
|
+
result << @theme.colorize_separator(@separator)
|
21
|
+
end
|
22
|
+
result
|
23
|
+
end
|
24
|
+
|
25
|
+
def compute_column_width_for(number_of_columns)
|
26
|
+
(number_of_columns - 1).to_s.length
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'minesweeper/core'
|
2
|
+
require 'rainbow'
|
3
|
+
require_relative 'header_printer'
|
4
|
+
require_relative 'row_printer'
|
5
|
+
require_relative 'theme/default_theme'
|
6
|
+
|
7
|
+
module Minesweeper
|
8
|
+
module Console
|
9
|
+
module PrettyPrinter
|
10
|
+
class MinefieldPrettyPrinter
|
11
|
+
def initialize(a_minefield, a_theme)
|
12
|
+
raise ArgumentError if a_minefield.nil?
|
13
|
+
@minefield = a_minefield
|
14
|
+
@theme = a_theme
|
15
|
+
@header_printer = HeaderPrinter.new('|', @theme)
|
16
|
+
@row_printer = RowPrinter.new('|', @theme)
|
17
|
+
end
|
18
|
+
|
19
|
+
def print
|
20
|
+
cells = @minefield.to_s
|
21
|
+
nb_columns = @minefield.row_count
|
22
|
+
generate_header(nb_columns) + generate_rows(cells, nb_columns)
|
23
|
+
end
|
24
|
+
|
25
|
+
def generate_header(nb_columns)
|
26
|
+
@header_printer.print(nb_columns) + "\n"
|
27
|
+
end
|
28
|
+
|
29
|
+
def generate_rows(cells, nb_columns)
|
30
|
+
max_column_width = (nb_columns - 1).to_s.length
|
31
|
+
result = ''
|
32
|
+
split_string_in_chunks(cells, nb_columns).each_with_index do |row, i|
|
33
|
+
result << @row_printer.print(i, row, max_column_width) + "\n"
|
34
|
+
end
|
35
|
+
result
|
36
|
+
end
|
37
|
+
|
38
|
+
def split_string_in_chunks(a_string, chunk_size)
|
39
|
+
a_string.scan(/.{#{chunk_size}}/)
|
40
|
+
end
|
41
|
+
|
42
|
+
private :split_string_in_chunks, :generate_header, :generate_rows
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Minesweeper
|
2
|
+
module Console
|
3
|
+
module PrettyPrinter
|
4
|
+
class RowPrinter
|
5
|
+
def initialize(separator, theme)
|
6
|
+
raise ArgumentError if separator.nil? || theme.nil?
|
7
|
+
@separator = separator
|
8
|
+
@theme = theme
|
9
|
+
end
|
10
|
+
|
11
|
+
def print(row_number, raw_row, column_width)
|
12
|
+
raise ArgumentError if column_width.nil?
|
13
|
+
raise ArgumentError if column_width < 1
|
14
|
+
raise ArgumentError if column_width < row_number.to_s.length
|
15
|
+
result = build_row_header(row_number, column_width)
|
16
|
+
raw_row.each_char do |c|
|
17
|
+
result << left_padding_for(c, column_width)
|
18
|
+
if (c =~ /\d+/)
|
19
|
+
result << @theme.colorize_mine_quantity(c)
|
20
|
+
else
|
21
|
+
result << @theme.colorize_cell_status(c)
|
22
|
+
end
|
23
|
+
result << @theme.colorize_separator(@separator)
|
24
|
+
end
|
25
|
+
result
|
26
|
+
end
|
27
|
+
|
28
|
+
def build_row_header(row_number, desired_length)
|
29
|
+
result = left_padding_for(row_number.to_s, desired_length)
|
30
|
+
result << @theme.colorize_header(row_number.to_s)
|
31
|
+
result << @theme.colorize_separator(@separator)
|
32
|
+
end
|
33
|
+
|
34
|
+
def left_padding_for(string, desired_length)
|
35
|
+
' ' * (desired_length - string.length)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Minesweeper
|
2
|
+
module Console
|
3
|
+
module PrettyPrinter
|
4
|
+
module Theme
|
5
|
+
class DefaultTheme
|
6
|
+
def initialize(a_colorizer)
|
7
|
+
@colorizer = a_colorizer
|
8
|
+
end
|
9
|
+
|
10
|
+
def colorize_header(a_string)
|
11
|
+
@colorizer.wrap(a_string).white
|
12
|
+
end
|
13
|
+
|
14
|
+
def colorize_separator(a_string)
|
15
|
+
a_string
|
16
|
+
end
|
17
|
+
|
18
|
+
def colorize_mine_quantity(a_string)
|
19
|
+
if (a_string == '0')
|
20
|
+
' '
|
21
|
+
else
|
22
|
+
@colorizer.wrap(a_string).red
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def colorize_cell_status(a_string)
|
27
|
+
if (a_string == 'F')
|
28
|
+
@colorizer.wrap(a_string).green
|
29
|
+
else
|
30
|
+
@colorizer.wrap(a_string).yellow
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Minesweeper
|
2
|
+
module Console
|
3
|
+
module PrettyPrinter
|
4
|
+
module Theme
|
5
|
+
class NullTheme
|
6
|
+
def colorize_header(a_string)
|
7
|
+
a_string
|
8
|
+
end
|
9
|
+
|
10
|
+
def colorize_separator(a_string)
|
11
|
+
a_string
|
12
|
+
end
|
13
|
+
|
14
|
+
def colorize_mine_quantity(a_string)
|
15
|
+
a_string
|
16
|
+
end
|
17
|
+
|
18
|
+
def colorize_cell_status(a_string)
|
19
|
+
a_string
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'minesweeper/console/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "minesweeper-console"
|
8
|
+
spec.version = Minesweeper::Console::VERSION
|
9
|
+
spec.authors = ["Sébastien Varlet"]
|
10
|
+
spec.email = ["sebastien.varlet@plumbee.co.uk"]
|
11
|
+
spec.summary = %q{Console UI for the minesweeper game.}
|
12
|
+
spec.description = %q{Console UI for the minesweeper game.}
|
13
|
+
spec.homepage = "https://github.com/svarlet/minesweeper-console"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.7"
|
22
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
23
|
+
spec.add_development_dependency "coveralls"
|
24
|
+
spec.add_development_dependency "guard"
|
25
|
+
spec.add_development_dependency "guard-test"
|
26
|
+
spec.add_development_dependency "guard-ctags-bundler"
|
27
|
+
spec.add_development_dependency "byebug"
|
28
|
+
spec.add_development_dependency "rainbow", "~> 2.0.0"
|
29
|
+
|
30
|
+
spec.add_runtime_dependency "minesweeper-core", "~> 2.0.0"
|
31
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require_relative '../../../test_helper'
|
2
|
+
require 'minesweeper/console/parser/command_parser'
|
3
|
+
require 'minesweeper/console/parser/invalid_command_parameters_error'
|
4
|
+
require 'minesweeper/console/parser/invalid_input_error'
|
5
|
+
require 'minesweeper/console/parser/reveal_command'
|
6
|
+
require 'minesweeper/console/parser/flag_command'
|
7
|
+
require 'minesweeper/console/parser/unflag_command'
|
8
|
+
|
9
|
+
module Minesweeper
|
10
|
+
module Console
|
11
|
+
module Parser
|
12
|
+
class CommandParserTest < Test::Unit::TestCase
|
13
|
+
def setup
|
14
|
+
@minefield = nil
|
15
|
+
@sut = CommandParser.new('')
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_raise_argument_error_when_initialize_parameter_is_nil
|
19
|
+
assert_raise(ArgumentError) { CommandParser.new }
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_parse_returns_a_null_command_when_user_input_is_nil_or_empty_or_newline
|
23
|
+
assert_instance_of(NullCommand, @sut.parse(nil))
|
24
|
+
assert_instance_of(NullCommand, @sut.parse(''))
|
25
|
+
assert_instance_of(NullCommand, @sut.parse("\n"))
|
26
|
+
assert_instance_of(NullCommand, @sut.parse(' '))
|
27
|
+
assert_instance_of(NullCommand, @sut.parse("\r"))
|
28
|
+
assert_instance_of(NullCommand, @sut.parse("\t"))
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_raises_error_when_the_first_token_is_not_a_supported_command
|
32
|
+
assert_raise(UnsupportedCommandError) { @sut.parse('? 0 0')}
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_raises_error_when_the_last_2_tokens_of_user_input_are_not_integers
|
36
|
+
assert_raise(InvalidCommandParametersError) { @sut.parse("R str str") }
|
37
|
+
assert_raise(InvalidCommandParametersError) { @sut.parse("R 0 str") }
|
38
|
+
assert_raise(InvalidCommandParametersError) { @sut.parse("R str 0") }
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_returns_a_reveal_command_when_first_token_of_user_input_is_R_or_r
|
42
|
+
assert_instance_of(RevealCommand, @sut.parse('r 0 0'))
|
43
|
+
assert_instance_of(RevealCommand, @sut.parse('R 0 0'))
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_returns_a_flag_command_when_first_token_of_user_input_is_f_or_F
|
47
|
+
assert_instance_of(FlagCommand, @sut.parse('f 0 0') )
|
48
|
+
assert_instance_of(FlagCommand, @sut.parse('F 0 0') )
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_parse_returns_an_unflag_command_when_first_token_of_user_input_is_u_or_U
|
52
|
+
assert_instance_of(UnflagCommand, @sut.parse('u 0 0') )
|
53
|
+
assert_instance_of(UnflagCommand, @sut.parse('U 0 0') )
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require_relative '../../../test_helper'
|
2
|
+
require 'minesweeper/console/parser/flag_command'
|
3
|
+
require_relative 'minefield_spy'
|
4
|
+
|
5
|
+
module Minesweeper
|
6
|
+
module Console
|
7
|
+
module Parser
|
8
|
+
class FlagCommandTest < Test::Unit::TestCase
|
9
|
+
def test_initialize_requires_a_minefield_and_2_coordinates
|
10
|
+
assert_nothing_raised { FlagCommand.new(nil, 4, 19) }
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_execute_should_call_flag_at_on_the_minefield_object
|
14
|
+
spy = MinefieldSpy.new
|
15
|
+
sut = FlagCommand.new(spy, 4, 19)
|
16
|
+
sut.execute
|
17
|
+
assert_equal(1, spy.methods_called.length)
|
18
|
+
assert_equal([:flag_at, 4, 19], spy.methods_called.pop)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Minesweeper
|
2
|
+
module Console
|
3
|
+
module Parser
|
4
|
+
class MinefieldSpy
|
5
|
+
attr_reader :methods_called
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@methods_called = []
|
9
|
+
end
|
10
|
+
|
11
|
+
def reveal_at(x, y)
|
12
|
+
@methods_called << [:reveal_at, x, y]
|
13
|
+
end
|
14
|
+
|
15
|
+
def flag_at(x, y)
|
16
|
+
@methods_called << [:flag_at, x, y]
|
17
|
+
end
|
18
|
+
|
19
|
+
def unflag_at(x, y)
|
20
|
+
@methods_called << [:unflag_at, x, y]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require_relative '../../../test_helper'
|
2
|
+
require 'minesweeper/console/parser/null_command'
|
3
|
+
|
4
|
+
module Minesweeper
|
5
|
+
module Console
|
6
|
+
module Parser
|
7
|
+
class NullCommandTest < Test::Unit::TestCase
|
8
|
+
def test_initializes_with_one_parameter
|
9
|
+
NullCommand.new(nil)
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_execute_does_nothing
|
13
|
+
assert_nothing_raised(StandardError) { NullCommand.new(nil).execute }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require_relative '../../../test_helper'
|
2
|
+
require_relative 'minefield_spy'
|
3
|
+
require 'minesweeper/console/parser/reveal_command'
|
4
|
+
|
5
|
+
module Minesweeper
|
6
|
+
module Console
|
7
|
+
module Parser
|
8
|
+
class RevealCommandTest < Test::Unit::TestCase
|
9
|
+
def test_initializes_requires_a_minefield_parameter_and_2_coordinates
|
10
|
+
assert_nothing_raised { RevealCommand.new(nil, 4, 19) }
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_execute_only_delegate_to_the_reveal_method_of_the_minefield_object
|
14
|
+
spy = MinefieldSpy.new
|
15
|
+
sut = RevealCommand.new(spy, 4, 19)
|
16
|
+
sut.execute
|
17
|
+
assert_equal(1, spy.methods_called.length)
|
18
|
+
assert_equal([:reveal_at, 4, 19], spy.methods_called.pop)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require_relative '../../../test_helper'
|
2
|
+
require 'minesweeper/console/parser/unflag_command'
|
3
|
+
require_relative 'minefield_spy'
|
4
|
+
|
5
|
+
module Minesweeper
|
6
|
+
module Console
|
7
|
+
module Parser
|
8
|
+
class UnflagCommandTest < Test::Unit::TestCase
|
9
|
+
def test_initialize_requires_a_minefield_and_2_coordinates
|
10
|
+
assert_nothing_raised { UnflagCommand.new(nil, 0, 0) }
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_execute_should_call_unflag_at_on_the_minefield_object
|
14
|
+
spy = MinefieldSpy.new
|
15
|
+
sut = UnflagCommand.new(spy, 4, 19)
|
16
|
+
sut.execute
|
17
|
+
assert_equal(1, spy.methods_called.length)
|
18
|
+
assert_equal([:unflag_at, 4, 19], spy.methods_called.pop)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'minesweeper/console/prettyprinter/header_printer'
|
2
|
+
require_relative '../../../test_helper'
|
3
|
+
require 'minesweeper/console/prettyprinter/theme/null_theme'
|
4
|
+
|
5
|
+
module Minesweeper
|
6
|
+
module Console
|
7
|
+
module PrettyPrinter
|
8
|
+
class HeaderPrinterTest < Test::Unit::TestCase
|
9
|
+
SEP = '§'
|
10
|
+
|
11
|
+
def setup
|
12
|
+
@printer = HeaderPrinter.new(SEP, Theme::NullTheme.new)
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_raises_error_when_initialized_with_nil_separator
|
16
|
+
assert_raise(ArgumentError) { HeaderPrinter.new(nil, Theme::NullTheme.new) }
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_raises_error_when_initialized_with_nil_theme
|
20
|
+
assert_raise(ArgumentError) { HeaderPrinter.new('.', nil) }
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_raises_error_when_number_of_columns_is_zero
|
24
|
+
assert_raise(ArgumentError) { @printer.print(0) }
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_raises_error_when_number_of_columns_is_negative
|
28
|
+
assert_raise(ArgumentError) { @printer.print(-1) }
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_makes_room_for_the_greatest_row_number
|
32
|
+
assert_match(/^ .*$/, @printer.print(1))
|
33
|
+
assert_match(/^ .*$/, @printer.print(11))
|
34
|
+
assert_match(/^ .*$/, @printer.print(101))
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_inserts_separator_after_first_column
|
38
|
+
assert_match(/^\s+#{SEP}.*$/, @printer.print(1))
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_first_column_number_is_zero
|
42
|
+
assert_match(/^\s#{SEP}0.*$/, @printer.print(1))
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_first_column_number_is_followed_by_separator
|
46
|
+
assert_match(/^.*#{SEP}$/, @printer.print(1))
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_prints_all_columns_number_upto_but_not_including_the_number_of_columns
|
50
|
+
assert_equal(" #{SEP}0#{SEP}1#{SEP}", @printer.print(2))
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_each_column_is_printed_with_the_width_of_the_greatest_column_number
|
54
|
+
result = @printer.print(100)
|
55
|
+
headers = result.split(SEP)
|
56
|
+
headers.each { |header| assert_equal(2, header.length) }
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'minesweeper/console/prettyprinter/minefield_pretty_printer'
|
2
|
+
require 'minesweeper/console/prettyprinter/theme/null_theme'
|
3
|
+
require_relative '../../../test_helper'
|
4
|
+
|
5
|
+
module Minesweeper
|
6
|
+
module Console
|
7
|
+
module PrettyPrinter
|
8
|
+
class MinefieldPrettyPrinterTest < Test::Unit::TestCase
|
9
|
+
def test_raises_error_when_initialized_with_a_nil_minefield
|
10
|
+
assert_raise(ArgumentError) { MinefieldPrettyPrinter.new(nil) }
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_output
|
14
|
+
verify_printing_of(" |0|1|\n0|1|2|\n1|H|F|\n", '12HF')
|
15
|
+
verify_printing_of(" |0|1|2|3|\n0|A|A|A|A|\n1|B|B|B|B|\n2|C|C|C|C|\n3|D|D|D|D|\n", 'AAAABBBBCCCCDDDD')
|
16
|
+
end
|
17
|
+
|
18
|
+
def verify_printing_of(expected, str_representation)
|
19
|
+
minefield = MinefieldMock.new(str_representation)
|
20
|
+
theme = Theme::NullTheme.new
|
21
|
+
printer = MinefieldPrettyPrinter.new(minefield, theme)
|
22
|
+
assert_equal(expected, printer.print)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class MinefieldMock
|
27
|
+
def initialize(string_representation)
|
28
|
+
@string_representation = string_representation
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_s
|
32
|
+
@string_representation
|
33
|
+
end
|
34
|
+
|
35
|
+
def row_count
|
36
|
+
Math.sqrt(@string_representation.length).to_i
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'minesweeper/console/prettyprinter/row_printer'
|
2
|
+
require_relative '../../../test_helper'
|
3
|
+
require 'minesweeper/console/prettyprinter/theme/null_theme'
|
4
|
+
|
5
|
+
module Minesweeper
|
6
|
+
module Console
|
7
|
+
module PrettyPrinter
|
8
|
+
class RowPrinterTest < Test::Unit::TestCase
|
9
|
+
SEP = '§'
|
10
|
+
|
11
|
+
def setup
|
12
|
+
@printer = RowPrinter.new(SEP, Theme::NullTheme.new)
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_raise_error_when_initialized_with_a_nil_separator
|
16
|
+
assert_raise(ArgumentError) { RowPrinter.new(nil, Theme::NullTheme.new) }
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_raise_error_when_initialized_with_a_nil_theme
|
20
|
+
assert_raise(ArgumentError) { RowPrinter.new('.', nil) }
|
21
|
+
end
|
22
|
+
def test_print_raises_error_when_column_width_is_nil
|
23
|
+
assert_raise(ArgumentError) { @printer.print(0, 'XYZ', nil) }
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_print_raises_error_when_columns_width_is_not_strictly_positive
|
27
|
+
assert_raise(ArgumentError) { @printer.print(0, 'XYZ', 0) }
|
28
|
+
assert_raise(ArgumentError) { @printer.print(0, 'XYZ', -1) }
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_print_raises_error_when_desired_column_width_is_smaller_than_row_number
|
32
|
+
assert_raise(ArgumentError) { @printer.print(10, 'XYZ', 1) }
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_prints_row_number_first
|
36
|
+
assert_match(/^0.*$/, @printer.print(0, 'HHHH', 1))
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_prints_separator_after_row_number
|
40
|
+
assert_match(/^\d+#{SEP}.*$/, @printer.print(0, 'HHHH', 1))
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_prints_each_character_of_the_sequence_separated_by_separator
|
44
|
+
assert_match(/^\d+#{SEP}X#{SEP}Y#{SEP}Z.*$/, @printer.print(0, 'XYZ', 1))
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_print_appends_separator_at_end_of_line
|
48
|
+
assert_match(/^.*#{SEP}$/, @printer.print(0, 'XYZ', 1))
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_enforces_column_width_on_each_column
|
52
|
+
result = @printer.print(0, 'XYZ', 3)
|
53
|
+
cells = result.split(SEP)
|
54
|
+
cells.each { |cell| assert_equal(3, cell.length) }
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require_relative '../../../../test_helper'
|
2
|
+
require 'minesweeper/console/prettyprinter/theme/default_theme'
|
3
|
+
require 'rainbow'
|
4
|
+
|
5
|
+
module Minesweeper
|
6
|
+
module Console
|
7
|
+
module PrettyPrinter
|
8
|
+
module Theme
|
9
|
+
class DefaultThemeTest < Test::Unit::TestCase
|
10
|
+
def test_is_initializable
|
11
|
+
DefaultTheme.new(@colorizer)
|
12
|
+
end
|
13
|
+
|
14
|
+
def setup
|
15
|
+
@colorizer = Rainbow.new
|
16
|
+
@theme = DefaultTheme.new(@colorizer)
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_class_implementation
|
20
|
+
class_specs = [:colorize_header, :colorize_separator, :colorize_mine_quantity, :colorize_cell_status]
|
21
|
+
class_specs.each do |spec|
|
22
|
+
assert_respond_to @theme, spec
|
23
|
+
assert_raise(ArgumentError) { @theme.send(spec) }
|
24
|
+
assert_equal('efhfh', do_with_colorizer_disabled { @theme.send(spec, 'efhfh') } )
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def do_with_colorizer_disabled(&block)
|
29
|
+
@colorizer.enabled = false
|
30
|
+
result = yield
|
31
|
+
@colorizer.enabled = true
|
32
|
+
result
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require_relative '../../../../test_helper'
|
2
|
+
require 'minesweeper/console/prettyprinter/theme/null_theme'
|
3
|
+
|
4
|
+
module Minesweeper
|
5
|
+
module Console
|
6
|
+
module PrettyPrinter
|
7
|
+
module Theme
|
8
|
+
class NullThemeTest < Test::Unit::TestCase
|
9
|
+
def test_is_initializable
|
10
|
+
NullTheme.new
|
11
|
+
end
|
12
|
+
|
13
|
+
def setup
|
14
|
+
@theme = NullTheme.new
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_class_implementation
|
18
|
+
class_specs = [:colorize_header, :colorize_separator, :colorize_mine_quantity, :colorize_cell_status]
|
19
|
+
class_specs.each do |spec|
|
20
|
+
assert_respond_to @theme, spec
|
21
|
+
assert_raise(ArgumentError) { @theme.send(spec) }
|
22
|
+
assert_equal('efhfh', @theme.send(spec, 'efhfh'))
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
data/test/test_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,221 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: minesweeper-console
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Sébastien Varlet
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-06-15 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.7'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.7'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: coveralls
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: guard
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: guard-test
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: guard-ctags-bundler
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: byebug
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - '>='
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - '>='
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rainbow
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ~>
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 2.0.0
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ~>
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: 2.0.0
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: minesweeper-core
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ~>
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: 2.0.0
|
132
|
+
type: :runtime
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ~>
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: 2.0.0
|
139
|
+
description: Console UI for the minesweeper game.
|
140
|
+
email:
|
141
|
+
- sebastien.varlet@plumbee.co.uk
|
142
|
+
executables:
|
143
|
+
- minesweeper
|
144
|
+
extensions: []
|
145
|
+
extra_rdoc_files: []
|
146
|
+
files:
|
147
|
+
- .coveralls.yml
|
148
|
+
- .gitignore
|
149
|
+
- .travis.yml
|
150
|
+
- Gemfile
|
151
|
+
- Guardfile
|
152
|
+
- LICENSE.txt
|
153
|
+
- README.md
|
154
|
+
- Rakefile
|
155
|
+
- bin/minesweeper
|
156
|
+
- lib/minesweeper/console.rb
|
157
|
+
- lib/minesweeper/console/game_loop.rb
|
158
|
+
- lib/minesweeper/console/parser/command_parser.rb
|
159
|
+
- lib/minesweeper/console/parser/flag_command.rb
|
160
|
+
- lib/minesweeper/console/parser/invalid_command_parameters_error.rb
|
161
|
+
- lib/minesweeper/console/parser/invalid_input_error.rb
|
162
|
+
- lib/minesweeper/console/parser/null_command.rb
|
163
|
+
- lib/minesweeper/console/parser/reveal_command.rb
|
164
|
+
- lib/minesweeper/console/parser/unflag_command.rb
|
165
|
+
- lib/minesweeper/console/parser/unsupported_command_error.rb
|
166
|
+
- lib/minesweeper/console/prettyprinter/header_printer.rb
|
167
|
+
- lib/minesweeper/console/prettyprinter/minefield_pretty_printer.rb
|
168
|
+
- lib/minesweeper/console/prettyprinter/row_printer.rb
|
169
|
+
- lib/minesweeper/console/prettyprinter/theme/default_theme.rb
|
170
|
+
- lib/minesweeper/console/prettyprinter/theme/null_theme.rb
|
171
|
+
- lib/minesweeper/console/version.rb
|
172
|
+
- minesweeper-console.gemspec
|
173
|
+
- test/minesweeper/console/parser/command_parser_test.rb
|
174
|
+
- test/minesweeper/console/parser/flag_command_test.rb
|
175
|
+
- test/minesweeper/console/parser/minefield_spy.rb
|
176
|
+
- test/minesweeper/console/parser/null_command_test.rb
|
177
|
+
- test/minesweeper/console/parser/reveal_command_test.rb
|
178
|
+
- test/minesweeper/console/parser/unflag_command_test.rb
|
179
|
+
- test/minesweeper/console/prettyprinter/header_printer_test.rb
|
180
|
+
- test/minesweeper/console/prettyprinter/minefield_pretty_printer_test.rb
|
181
|
+
- test/minesweeper/console/prettyprinter/row_printer_test.rb
|
182
|
+
- test/minesweeper/console/prettyprinter/theme/default_theme_test.rb
|
183
|
+
- test/minesweeper/console/prettyprinter/theme/null_theme_test.rb
|
184
|
+
- test/test_helper.rb
|
185
|
+
homepage: https://github.com/svarlet/minesweeper-console
|
186
|
+
licenses:
|
187
|
+
- MIT
|
188
|
+
metadata: {}
|
189
|
+
post_install_message:
|
190
|
+
rdoc_options: []
|
191
|
+
require_paths:
|
192
|
+
- lib
|
193
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
194
|
+
requirements:
|
195
|
+
- - '>='
|
196
|
+
- !ruby/object:Gem::Version
|
197
|
+
version: '0'
|
198
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
199
|
+
requirements:
|
200
|
+
- - '>='
|
201
|
+
- !ruby/object:Gem::Version
|
202
|
+
version: '0'
|
203
|
+
requirements: []
|
204
|
+
rubyforge_project:
|
205
|
+
rubygems_version: 2.4.5
|
206
|
+
signing_key:
|
207
|
+
specification_version: 4
|
208
|
+
summary: Console UI for the minesweeper game.
|
209
|
+
test_files:
|
210
|
+
- test/minesweeper/console/parser/command_parser_test.rb
|
211
|
+
- test/minesweeper/console/parser/flag_command_test.rb
|
212
|
+
- test/minesweeper/console/parser/minefield_spy.rb
|
213
|
+
- test/minesweeper/console/parser/null_command_test.rb
|
214
|
+
- test/minesweeper/console/parser/reveal_command_test.rb
|
215
|
+
- test/minesweeper/console/parser/unflag_command_test.rb
|
216
|
+
- test/minesweeper/console/prettyprinter/header_printer_test.rb
|
217
|
+
- test/minesweeper/console/prettyprinter/minefield_pretty_printer_test.rb
|
218
|
+
- test/minesweeper/console/prettyprinter/row_printer_test.rb
|
219
|
+
- test/minesweeper/console/prettyprinter/theme/default_theme_test.rb
|
220
|
+
- test/minesweeper/console/prettyprinter/theme/null_theme_test.rb
|
221
|
+
- test/test_helper.rb
|