minesweeper-curses 0.4.0 → 0.4.1
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 +5 -5
- data/.rubocop.yml +2 -2
- data/.ruby-version +1 -1
- data/.travis.yml +3 -1
- data/Rakefile +3 -6
- data/bin/console +1 -0
- data/bin/minesweeper-curses +1 -0
- data/lib/minesweeper.rb +4 -4
- data/lib/minesweeper/board.rb +29 -31
- data/lib/minesweeper/board_builder.rb +1 -1
- data/lib/minesweeper/bomb_injector.rb +1 -1
- data/lib/minesweeper/cells/base.rb +44 -0
- data/lib/minesweeper/cells/bomb.rb +17 -0
- data/lib/minesweeper/cells/cell.rb +17 -0
- data/lib/minesweeper/cells/state.rb +23 -0
- data/lib/minesweeper/game_initializer.rb +0 -6
- data/lib/minesweeper/ui.rb +13 -1
- data/lib/minesweeper/version.rb +1 -1
- data/readme.md +4 -2
- metadata +7 -8
- data/lib/minesweeper/base_cell.rb +0 -42
- data/lib/minesweeper/bomb_cell.rb +0 -15
- data/lib/minesweeper/cell.rb +0 -15
- data/lib/minesweeper/cell_state.rb +0 -21
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: b505c67f37bbf83ec7880ebfc8bcd879e386733c15640dbd469643770589e9c1
|
4
|
+
data.tar.gz: c82a9785a2bfda4c76f8b6c840ab83ca76376a75944bb5f830b748511750dc92
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 750e136e11cc3019c932e8d3557e608461cabdb2e316411827883ecca20f8d8068111052899b675d3d2b9d5dd18a254b5233023f71988a8730ceb11d2861525d
|
7
|
+
data.tar.gz: ba164d83089740fb9db67eed88e3f324fbf37f52f25703b17aa7732e177b01c91019c146fb64ac66f5aabac209d23184b9c94bc6f3d7233e11202ade66367a93
|
data/.rubocop.yml
CHANGED
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.
|
1
|
+
2.5.3
|
data/.travis.yml
CHANGED
data/Rakefile
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'bundler/gem_tasks'
|
2
4
|
require 'rake/testtask'
|
3
5
|
|
@@ -7,9 +9,4 @@ Rake::TestTask.new(:test) do |t|
|
|
7
9
|
t.test_files = FileList['test/**/*_test.rb']
|
8
10
|
end
|
9
11
|
|
10
|
-
task :
|
11
|
-
|
12
|
-
task :build_and_install do
|
13
|
-
sh('bundle install')
|
14
|
-
sh("gem install ./pkg/minesweeper-#{Minesweeper::VERSION}.gem")
|
15
|
-
end
|
12
|
+
task default: :test
|
data/bin/console
CHANGED
data/bin/minesweeper-curses
CHANGED
data/lib/minesweeper.rb
CHANGED
@@ -11,12 +11,12 @@ require_relative 'minesweeper/board_params'
|
|
11
11
|
require_relative 'minesweeper/board'
|
12
12
|
require_relative 'minesweeper/board_builder'
|
13
13
|
require_relative 'minesweeper/params_builder'
|
14
|
-
require_relative 'minesweeper/
|
15
|
-
require_relative 'minesweeper/cell'
|
16
|
-
require_relative 'minesweeper/
|
14
|
+
require_relative 'minesweeper/cells/base'
|
15
|
+
require_relative 'minesweeper/cells/cell'
|
16
|
+
require_relative 'minesweeper/cells/bomb'
|
17
17
|
require_relative 'minesweeper/bomb_injector'
|
18
18
|
require_relative 'minesweeper/game_initializer'
|
19
|
-
require_relative 'minesweeper/
|
19
|
+
require_relative 'minesweeper/cells/state'
|
20
20
|
|
21
21
|
module Minesweeper
|
22
22
|
end
|
data/lib/minesweeper/board.rb
CHANGED
@@ -9,25 +9,23 @@ module Minesweeper
|
|
9
9
|
LEFT_RIGHT_PADDING = 2
|
10
10
|
SPACE = ' '
|
11
11
|
|
12
|
-
def_delegators :@window, :curx, :cury
|
13
12
|
def_delegators :board_params, :height, :width
|
14
13
|
|
15
|
-
attr_reader :board_params, :cells, :
|
14
|
+
attr_reader :board_params, :cells, :ui
|
16
15
|
|
17
16
|
def initialize(board_params)
|
18
17
|
@board_params = board_params
|
19
|
-
@
|
20
|
-
@cells
|
18
|
+
@ui = Minesweeper::Ui
|
19
|
+
@cells = []
|
21
20
|
end
|
22
21
|
|
23
22
|
def play(stdy = nil, stdx = nil)
|
24
|
-
window.keypad = true
|
25
23
|
draw_board
|
26
|
-
|
24
|
+
ui.setpos(stdy, stdx) if stdx && stdy
|
27
25
|
noecho
|
28
26
|
|
29
27
|
loop do
|
30
|
-
ch =
|
28
|
+
ch = ui.getch
|
31
29
|
case ch
|
32
30
|
when KEY_UP
|
33
31
|
move_up
|
@@ -42,7 +40,7 @@ module Minesweeper
|
|
42
40
|
when SPACE
|
43
41
|
toggle_bomb_flag
|
44
42
|
end
|
45
|
-
play(cury, curx)
|
43
|
+
play(ui.cury, ui.curx)
|
46
44
|
end
|
47
45
|
rescue GameWon, GameOver => e
|
48
46
|
end_game(e)
|
@@ -52,30 +50,30 @@ module Minesweeper
|
|
52
50
|
private
|
53
51
|
|
54
52
|
def draw_board
|
55
|
-
|
53
|
+
ui.clear
|
56
54
|
cells.each_index do |row_index|
|
57
55
|
(0..(width * 3 - 1)).each_slice(3).with_index do |cell_ary, index|
|
58
56
|
cell = cells[row_index][index]
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
57
|
+
ui.setpos(row_index, cell_ary[0])
|
58
|
+
ui.attron(color_pair(COLOR_BLUE)) { ui.addstr '[' }
|
59
|
+
ui.attron(color_pair(cell.color)) { ui.addstr cell.view }
|
60
|
+
ui.attron(color_pair(COLOR_BLUE)) { ui.addstr ']' }
|
63
61
|
end
|
64
62
|
end
|
65
|
-
|
66
|
-
|
63
|
+
ui.refresh
|
64
|
+
ui.setpos(0, 1)
|
67
65
|
end
|
68
66
|
|
69
67
|
def cell_x
|
70
|
-
curx / STEP
|
68
|
+
ui.curx / STEP
|
71
69
|
end
|
72
70
|
|
73
71
|
def open_cell
|
74
|
-
open_original(cury, cell_x)
|
72
|
+
open_original(ui.cury, cell_x)
|
75
73
|
end
|
76
74
|
|
77
75
|
def toggle_bomb_flag
|
78
|
-
cell = cells[cury][cell_x]
|
76
|
+
cell = cells[ui.cury][cell_x]
|
79
77
|
cell.toggle_bomb_flag!
|
80
78
|
raise GameWon if game_won?
|
81
79
|
end
|
@@ -111,33 +109,33 @@ module Minesweeper
|
|
111
109
|
end
|
112
110
|
|
113
111
|
def move_up
|
114
|
-
return if cury.zero?
|
115
|
-
|
112
|
+
return if ui.cury.zero?
|
113
|
+
ui.setpos(ui.cury - 1, ui.curx)
|
116
114
|
end
|
117
115
|
|
118
116
|
def move_down
|
119
|
-
return if cury + 1 >= height
|
120
|
-
|
117
|
+
return if ui.cury + 1 >= height
|
118
|
+
ui.setpos(ui.cury + 1, ui.curx)
|
121
119
|
end
|
122
120
|
|
123
121
|
def move_left
|
124
|
-
return if curx <= LEFT_RIGHT_PADDING
|
125
|
-
|
122
|
+
return if ui.curx <= LEFT_RIGHT_PADDING
|
123
|
+
ui.setpos(ui.cury, ui.curx - STEP)
|
126
124
|
end
|
127
125
|
|
128
126
|
def move_right
|
129
|
-
return if curx >= (width * 3 - LEFT_RIGHT_PADDING)
|
130
|
-
|
127
|
+
return if ui.curx >= (width * 3 - LEFT_RIGHT_PADDING)
|
128
|
+
ui.setpos(ui.cury, ui.curx + STEP)
|
131
129
|
end
|
132
130
|
|
133
131
|
def end_game(e)
|
134
132
|
found_bombs_count = found_bombs.count
|
135
133
|
reveal_bombs
|
136
134
|
draw_board
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
135
|
+
ui.setpos(height + 1, 0)
|
136
|
+
ui.addstr e.message
|
137
|
+
ui.setpos(height + 3, 0)
|
138
|
+
ui.addstr <<~STR
|
141
139
|
Game Stats: you have found #{found_bombs_count} out of #{bombs.count} bombs
|
142
140
|
|
143
141
|
- `R` to replay with same parameters
|
@@ -150,7 +148,7 @@ module Minesweeper
|
|
150
148
|
# used when user won/lose game & decided to begin anew
|
151
149
|
# eventually will be moved to game initializer
|
152
150
|
def start_or_restart_game
|
153
|
-
case
|
151
|
+
case ui.getch
|
154
152
|
when ENTER
|
155
153
|
echo
|
156
154
|
game_initializer.start
|
@@ -18,7 +18,7 @@ module Minesweeper
|
|
18
18
|
cell_index = random_cell
|
19
19
|
cell = board.cells[row_index][cell_index]
|
20
20
|
unless cell.bomb?
|
21
|
-
board.cells[row_index][cell_index] =
|
21
|
+
board.cells[row_index][cell_index] = Cells::Bomb.new
|
22
22
|
number -= 1
|
23
23
|
end
|
24
24
|
add_bombs(number)
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Minesweeper
|
4
|
+
module Cells
|
5
|
+
class Base
|
6
|
+
extend Forwardable
|
7
|
+
|
8
|
+
def_delegators :@state, :view, :color, :opened?, :marked_as_bomb?
|
9
|
+
|
10
|
+
attr_reader :state
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
@state = initial_state
|
14
|
+
end
|
15
|
+
|
16
|
+
def bomb?
|
17
|
+
raise NotImplementedError, 'defined in subclass'
|
18
|
+
end
|
19
|
+
|
20
|
+
def toggle_bomb_flag!
|
21
|
+
return if opened?
|
22
|
+
if marked_as_bomb?
|
23
|
+
state.view = ' '
|
24
|
+
state.color = COLOR_MAGENTA
|
25
|
+
state.status = :initial
|
26
|
+
else
|
27
|
+
state.view = '*'
|
28
|
+
state.color = COLOR_MAGENTA
|
29
|
+
state.status = :marked_as_bomb
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def open!(*)
|
34
|
+
raise NotImplementedError, 'defined in subclass'
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def initial_state
|
40
|
+
State.new(color: COLOR_MAGENTA, view: ' ', status: :initial)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Minesweeper
|
4
|
+
module Cells
|
5
|
+
class Bomb < Base
|
6
|
+
def bomb?
|
7
|
+
true
|
8
|
+
end
|
9
|
+
|
10
|
+
def open!(*)
|
11
|
+
state.view = '*'
|
12
|
+
state.color = marked_as_bomb? ? COLOR_WHITE : COLOR_RED
|
13
|
+
state.status = :opened
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Minesweeper
|
4
|
+
module Cells
|
5
|
+
class Cell < Base
|
6
|
+
def bomb?
|
7
|
+
false
|
8
|
+
end
|
9
|
+
|
10
|
+
def open!(number_of_boms_nearby)
|
11
|
+
state.view = number_of_boms_nearby.to_s
|
12
|
+
state.color = COLOR_CYAN
|
13
|
+
state.status = :opened
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Minesweeper
|
4
|
+
module Cells
|
5
|
+
class State
|
6
|
+
attr_accessor :color, :view, :status
|
7
|
+
|
8
|
+
def initialize(color:, status:, view:)
|
9
|
+
@view = view
|
10
|
+
@color = color
|
11
|
+
@status = status
|
12
|
+
end
|
13
|
+
|
14
|
+
def opened?
|
15
|
+
status == :opened
|
16
|
+
end
|
17
|
+
|
18
|
+
def marked_as_bomb?
|
19
|
+
status == :marked_as_bomb
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -2,10 +2,6 @@
|
|
2
2
|
|
3
3
|
module Minesweeper
|
4
4
|
class GameInitializer
|
5
|
-
def initialize
|
6
|
-
@window = nil
|
7
|
-
end
|
8
|
-
|
9
5
|
def start
|
10
6
|
init_curses
|
11
7
|
Ui.greeting_message
|
@@ -29,8 +25,6 @@ module Minesweeper
|
|
29
25
|
.play
|
30
26
|
end
|
31
27
|
|
32
|
-
attr_reader :window
|
33
|
-
|
34
28
|
def init_curses
|
35
29
|
init_screen
|
36
30
|
init_colors
|
data/lib/minesweeper/ui.rb
CHANGED
@@ -20,7 +20,19 @@ module Minesweeper
|
|
20
20
|
instance.respond_to?(:method_name) || super
|
21
21
|
end
|
22
22
|
|
23
|
-
def_delegators :window,
|
23
|
+
def_delegators :window,
|
24
|
+
:clear,
|
25
|
+
:addch,
|
26
|
+
:addstr,
|
27
|
+
:refresh,
|
28
|
+
:maxy,
|
29
|
+
:maxx,
|
30
|
+
:getstr,
|
31
|
+
:setpos,
|
32
|
+
:attron,
|
33
|
+
:getch,
|
34
|
+
:curx,
|
35
|
+
:cury
|
24
36
|
|
25
37
|
def greeting_message
|
26
38
|
clear
|
data/lib/minesweeper/version.rb
CHANGED
data/readme.md
CHANGED
@@ -7,7 +7,7 @@
|
|
7
7
|
|
8
8
|
#### Requirements
|
9
9
|
|
10
|
-
- ruby 2.4
|
10
|
+
- ruby 2.4 or higher
|
11
11
|
|
12
12
|
#### Setup
|
13
13
|
|
@@ -17,7 +17,9 @@
|
|
17
17
|
|
18
18
|
- `git clone git@github.com:ruba-ruba/minesweeper.git`
|
19
19
|
- `cd minesweeper`
|
20
|
-
- `
|
20
|
+
- `gem install bundler`
|
21
|
+
- `bundle install`
|
22
|
+
- `rake install`
|
21
23
|
|
22
24
|
#### Launching
|
23
25
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: minesweeper-curses
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mykhailo Rybak
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-01-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: curses
|
@@ -116,14 +116,14 @@ files:
|
|
116
116
|
- bin/minesweeper-curses
|
117
117
|
- bin/setup
|
118
118
|
- lib/minesweeper.rb
|
119
|
-
- lib/minesweeper/base_cell.rb
|
120
119
|
- lib/minesweeper/board.rb
|
121
120
|
- lib/minesweeper/board_builder.rb
|
122
121
|
- lib/minesweeper/board_params.rb
|
123
|
-
- lib/minesweeper/bomb_cell.rb
|
124
122
|
- lib/minesweeper/bomb_injector.rb
|
125
|
-
- lib/minesweeper/
|
126
|
-
- lib/minesweeper/
|
123
|
+
- lib/minesweeper/cells/base.rb
|
124
|
+
- lib/minesweeper/cells/bomb.rb
|
125
|
+
- lib/minesweeper/cells/cell.rb
|
126
|
+
- lib/minesweeper/cells/state.rb
|
127
127
|
- lib/minesweeper/exceptions.rb
|
128
128
|
- lib/minesweeper/game_initializer.rb
|
129
129
|
- lib/minesweeper/params_builder.rb
|
@@ -151,8 +151,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
151
151
|
- !ruby/object:Gem::Version
|
152
152
|
version: '0'
|
153
153
|
requirements: []
|
154
|
-
|
155
|
-
rubygems_version: 2.6.11
|
154
|
+
rubygems_version: 3.0.1
|
156
155
|
signing_key:
|
157
156
|
specification_version: 4
|
158
157
|
summary: Minesweeper CLI game using curses
|
@@ -1,42 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Minesweeper
|
4
|
-
class BaseCell
|
5
|
-
extend Forwardable
|
6
|
-
|
7
|
-
def_delegators :@state, :view, :color, :opened?, :marked_as_bomb?
|
8
|
-
|
9
|
-
attr_reader :state
|
10
|
-
|
11
|
-
def initialize
|
12
|
-
@state = initial_state
|
13
|
-
end
|
14
|
-
|
15
|
-
def bomb?
|
16
|
-
raise NotImplementedError, 'defined in subclass'
|
17
|
-
end
|
18
|
-
|
19
|
-
def toggle_bomb_flag!
|
20
|
-
return if opened?
|
21
|
-
if marked_as_bomb?
|
22
|
-
state.view = ' '
|
23
|
-
state.color = COLOR_MAGENTA
|
24
|
-
state.status = :initial
|
25
|
-
else
|
26
|
-
state.view = '*'
|
27
|
-
state.color = COLOR_MAGENTA
|
28
|
-
state.status = :marked_as_bomb
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
def open!(*)
|
33
|
-
raise NotImplementedError, 'defined in subclass'
|
34
|
-
end
|
35
|
-
|
36
|
-
private
|
37
|
-
|
38
|
-
def initial_state
|
39
|
-
CellState.new(color: COLOR_MAGENTA, view: ' ', status: :initial)
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
data/lib/minesweeper/cell.rb
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Minesweeper
|
4
|
-
class Cell < BaseCell
|
5
|
-
def bomb?
|
6
|
-
false
|
7
|
-
end
|
8
|
-
|
9
|
-
def open!(number_of_boms_nearby)
|
10
|
-
state.view = number_of_boms_nearby.to_s
|
11
|
-
state.color = COLOR_CYAN
|
12
|
-
state.status = :opened
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
@@ -1,21 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Minesweeper
|
4
|
-
class CellState
|
5
|
-
attr_accessor :color, :view, :status
|
6
|
-
|
7
|
-
def initialize(color:, status:, view:)
|
8
|
-
@view = view
|
9
|
-
@color = color
|
10
|
-
@status = status
|
11
|
-
end
|
12
|
-
|
13
|
-
def opened?
|
14
|
-
status == :opened
|
15
|
-
end
|
16
|
-
|
17
|
-
def marked_as_bomb?
|
18
|
-
status == :marked_as_bomb
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|