minesweeper 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b10193144ceaeb6995ac3a3a4c747953ac4cc346
4
+ data.tar.gz: 28a61a483e56e28d921f29a8e6b46b47c1783e7b
5
+ SHA512:
6
+ metadata.gz: 635519e896eba1fe969dcc1c525a39c8a970ed2dcae841c4936a1e05d5e8495f2ae7354adf48db25fb8806e280c7400b62de89bd7200347354625b4c72e33ffe
7
+ data.tar.gz: 84589c0690f06746c87c49276a9b03aeb59f64c2c787531dbc180e818b9b7b0e935dfcc3be0268d55812a2fb3785536d45e25b61ee531f8c04a5142b9cee5b27
data/.DS_Store ADDED
Binary file
data/.gitignore ADDED
@@ -0,0 +1,14 @@
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
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem 'rspec'
4
+ gem 'guard-rspec', require: false
data/Guardfile ADDED
@@ -0,0 +1,77 @@
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 feature)
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 ('.'), the you will want to move the Guardfile
18
+ ## 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
+ # Note: The cmd option is now required due to the increasing number of ways
27
+ # rspec may be run, below are examples of the most common uses.
28
+ # * bundler: 'bundle exec rspec'
29
+ # * bundler binstubs: 'bin/rspec'
30
+ # * spring: 'bin/rspec' (This will use spring if running and you have
31
+ # installed the spring binstubs per the docs)
32
+ # * zeus: 'zeus rspec' (requires the server to be started separately)
33
+ # * 'just' rspec: 'rspec'
34
+
35
+ guard :rspec, cmd: "bundle exec rspec" do
36
+ require "guard/rspec/dsl"
37
+ dsl = Guard::RSpec::Dsl.new(self)
38
+
39
+ # Feel free to open issues for suggestions and improvements
40
+
41
+ # RSpec files
42
+ rspec = dsl.rspec
43
+ watch(rspec.spec_helper) { rspec.spec_dir }
44
+ watch(rspec.spec_support) { rspec.spec_dir }
45
+ watch(rspec.spec_files)
46
+
47
+ # Ruby files
48
+ ruby = dsl.ruby
49
+ dsl.watch_spec_files_for(ruby.lib_files)
50
+
51
+ # Rails files
52
+ rails = dsl.rails(view_extensions: %w(erb haml slim))
53
+ dsl.watch_spec_files_for(rails.app_files)
54
+ dsl.watch_spec_files_for(rails.views)
55
+
56
+ watch(rails.controllers) do |m|
57
+ [
58
+ rspec.spec.("routing/#{m[1]}_routing"),
59
+ rspec.spec.("controllers/#{m[1]}_controller"),
60
+ rspec.spec.("acceptance/#{m[1]}")
61
+ ]
62
+ end
63
+
64
+ # Rails config changes
65
+ watch(rails.spec_helper) { rspec.spec_dir }
66
+ watch(rails.routes) { "#{rspec.spec_dir}/routing" }
67
+ watch(rails.app_controller) { "#{rspec.spec_dir}/controllers" }
68
+
69
+ # Capybara features specs
70
+ watch(rails.view_dirs) { |m| rspec.spec.("features/#{m[1]}") }
71
+
72
+ # Turnip features and steps
73
+ watch(%r{^spec/acceptance/(.+)\.feature$})
74
+ watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) do |m|
75
+ Dir[File.join("**/#{m[1]}.feature")][0] || "spec/acceptance"
76
+ end
77
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Michael Alexander
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,55 @@
1
+ Minesweeper TDD Solution
2
+ ========================
3
+
4
+ If you got even most of this project done, you can consider yourself *far* beyond a beginner in Ruby. You're TDDing like the pros, and learning to decompose your methods. Most of all, what you should have learned from this is that smaller and more isolated methods are easier to test, and it's much easier to set up an example than to try to test by absolute logical necessity.
5
+
6
+ ##Points of Interest
7
+
8
+ - the game loop itself is hard to test beyond expecting messages to be sent to certain objects
9
+ + make sure to stub out victory conditions so your test doesn't get caught in an infinite loop
10
+ - the board is where the meat of the logic is, and that's where unit testing is most effective
11
+ - to test methods like counting adjacent mines, cheat
12
+ + use a `before` clause to set mines exactly where you want them
13
+ + then run your `#num_adjacent_mines` method
14
+ - testing automated mine clearing is hard. don't look for the perfect algorithm here
15
+ + instead, see if a mine with zero others around it also clears off the 8 mines surrounding it
16
+ - remember that the `equal` method and the `eq` method in Rspec are not the same
17
+ + if something `equal`s `true`, then it literally IS that object
18
+ + if it `eq`s `true`, that's normal Ruby Boolean truthiness
19
+ + `equal` is VERY useful to make sure boolean methods actually work!
20
+ -_Bonus:_ when working with 2D arrays, remember you can always use the `#flatten` method to get at the elements inside.
21
+ - this comes in really handy when you want to compare two 2D arrays for equality or set all their elements equal
22
+ - `@board.grid.flatten.each {|s| s.mine = false }` is a one-liner to remove every mine from the board, as another example
23
+
24
+
25
+ ## A bonus
26
+
27
+ You can iteratively generate expectations, even stack them. It's not often the right way to go, but every once in a while it's perfect.
28
+
29
+ See here:
30
+
31
+ ```code-rspec
32
+
33
+ context 'if the space has zero mines nearby' do
34
+ # ...other stuff
35
+
36
+ it 'should uncover all adjacent mines' do
37
+
38
+ subject.mark_clear(3,3)
39
+
40
+ # whoa! you can iterate expectations!
41
+ # this way, the test fails if any one of these
42
+ # *NINE* expect clauses fail
43
+ # which is to say, if any adjacent square remains hidden
44
+
45
+ 2.upto(4) do |x|
46
+ 2.upto(4) do |y|
47
+ expect(subject[x][y].visible).to equal true
48
+ end
49
+ end
50
+
51
+ end
52
+ end
53
+ ```
54
+
55
+ *NOTE: This solution repo is copyrighted material for your private use only and not to be shared outside of Viking Code School.*
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
data/lib/.DS_Store ADDED
Binary file
Binary file
@@ -0,0 +1,3 @@
1
+ module Minesweeper
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,278 @@
1
+ require 'minesweeper/version.rb'
2
+
3
+ class Board
4
+ attr_reader :grid, :size
5
+ attr_accessor :flags_remaining
6
+
7
+ def initialize(size = 10)
8
+ raise "size out of range!" unless size.between?(8, 25)
9
+ @size = size
10
+ @grid = Array.new(size){ Array.new(size){ Space.new } }
11
+
12
+ place_mines
13
+ count_nearby_mines
14
+
15
+ #must be after mine placement
16
+ @flags_remaining = mine_count
17
+ end
18
+
19
+ # this took lots of refactoring!!!
20
+ def mine_count
21
+ grid.flatten.count { |space| space.mine }
22
+ end
23
+
24
+ def render
25
+ (self.size-1).downto(0) do |y|
26
+ print "#{y}|"
27
+ (0).upto(self.size-1) do |x|
28
+ render_cell(x, y)
29
+ print " "
30
+ end
31
+ puts "|\n"
32
+ end
33
+
34
+ print " "
35
+ print "--" * size
36
+ puts "\n"
37
+ print " "
38
+ 0.upto(self.size-1) {|x| print " #{x}"}
39
+ puts "\n"
40
+ puts "Flags remaining: #{flags_remaining}\n"
41
+ nil
42
+ end
43
+
44
+ #show everything if you lose
45
+ def endgame_render
46
+ self.grid.flatten.each {|space| space.visible = true }
47
+ render
48
+ end
49
+
50
+ # rather than just calling board.grid[row][col]
51
+ # this passes the grid directly through
52
+ # so you can call board[row][col]
53
+
54
+ def [](index)
55
+ self.grid[index]
56
+ end
57
+
58
+
59
+
60
+ def place_flag( x, y )
61
+ return false if flags_remaining <= 0
62
+ return false if self[x][y].visible
63
+
64
+ self[x][y].flagged = true
65
+ self.flags_remaining -= 1
66
+ true
67
+ end
68
+
69
+ def mark_clear( x, y )
70
+ return false if self[x][y].visible
71
+ self[x][y].visible = true
72
+
73
+ if self[x][y].zero_nearby?
74
+
75
+ #mark all of them as well
76
+ adjacent_spaces(x, y).each do |coords|
77
+ adj_x, adj_y = coords[0], coords[1]
78
+ mark_clear(adj_x, adj_y)
79
+ end
80
+
81
+ end
82
+
83
+ true
84
+ end
85
+
86
+ # all non-mine spaces are visible
87
+ def victory?
88
+ self.grid.flatten.select {|space| !space.mine }.
89
+ all? {|space| space.visible }
90
+ end
91
+
92
+
93
+ def game_lost?
94
+ touched_a_mine?
95
+ end
96
+
97
+ def num_adjacent_mines(x, y)
98
+ mine_count = 0
99
+
100
+ adjacent_spaces(x, y).each do |coords|
101
+ adj_x, adj_y = coords[0], coords[1]
102
+ mine_count += 1 if self.grid[adj_x][adj_y].mine
103
+ end
104
+
105
+ mine_count
106
+ end
107
+
108
+
109
+ private
110
+
111
+ def render_cell(x, y)
112
+ cell = self.grid[x][y]
113
+
114
+ if !cell.visible && cell.flagged
115
+ print "F"
116
+ elsif !cell.visible
117
+ print "_"
118
+ elsif cell.mine
119
+ print "M"
120
+ else
121
+ print cell.nearby_mines
122
+ end
123
+ end
124
+
125
+
126
+ # oops. you found a mine
127
+ def touched_a_mine?
128
+ self.grid.flatten.any?{ |cell| cell.visible && cell.mine }
129
+ end
130
+
131
+
132
+ # used to decide whether recursive clearing
133
+ # is possible on a space (No mine, not visible yet)
134
+ # AND has 0 nearby mines
135
+ def can_clear? ( x, y )
136
+ !self[x][y].visible &&
137
+ !self[x][y].mine &&
138
+ self[x][y].nearby_mines == 0
139
+ end
140
+
141
+ def count_nearby_mines
142
+ 0.upto(self.grid.size - 1) do |x|
143
+ 0.upto(self.grid.size - 1) do |y|
144
+ self.grid[x][y].nearby_mines = num_adjacent_mines(x, y)
145
+ end
146
+ end
147
+ end
148
+
149
+ def adjacent_spaces(x,y)
150
+
151
+ coords = []
152
+
153
+ (x - 1).upto(x + 1) do |adj_x|
154
+ (y - 1).upto(y + 1) do |adj_y|
155
+
156
+ # don't count yourself
157
+ next if ((x == adj_x) && (y == adj_y))
158
+
159
+ #if coords are within the bounds of the grid
160
+ if (adj_x >= 0 && adj_y >= 0) && (adj_x < self.size && adj_y < self.size)
161
+
162
+ #add them to the list of adjacent coordinates
163
+ coords.push([adj_x, adj_y])
164
+ end
165
+ end
166
+ end
167
+
168
+ coords
169
+ end
170
+
171
+
172
+ def place_mines
173
+
174
+ mines_to_place = [ (self.size - 7)**2, 100].min
175
+
176
+ while mines_to_place > 0
177
+ x, y = rand(self.size), rand(self.size)
178
+
179
+ unless self.grid[x][y].mine
180
+ self.grid[x][y].mine = true
181
+ mines_to_place -= 1
182
+ end
183
+
184
+ end
185
+
186
+ end
187
+
188
+
189
+ end
190
+
191
+ class Space
192
+ attr_accessor :visible, :flagged, :mine, :nearby_mines
193
+
194
+ def initialize
195
+ @visible = false
196
+ @flagged = false
197
+ @mine = false
198
+ @nearby_mines = nil
199
+ end
200
+
201
+ def clear?
202
+ visible && !mine
203
+ end
204
+
205
+ def zero_nearby?
206
+ clear? && self.nearby_mines == 0
207
+ end
208
+ end
209
+
210
+
211
+
212
+ class Player
213
+ def initialize(board)
214
+ @board = board
215
+ end
216
+
217
+ def take_turn
218
+
219
+ until make_move do
220
+ puts "That didn't work. Try again."
221
+ end
222
+ end
223
+
224
+ private
225
+
226
+ def make_move
227
+ puts "Mark a square as (C)lear\n or (F)lag it as a mine?"
228
+ print "> "
229
+ choice = gets.chomp.upcase
230
+
231
+ print "Choose coordinates in the form of x, y: "
232
+ x, y = gets.chomp.split(',').map{|c| c.to_i }
233
+
234
+ if choice == "F"
235
+ @board.place_flag(x, y)
236
+ else
237
+ @board.mark_clear(x, y)
238
+ end
239
+ end
240
+
241
+ end
242
+
243
+
244
+ class Game
245
+
246
+ attr_reader :player, :board
247
+
248
+ def initialize
249
+ @board = Board.new
250
+ @player = Player.new(@board)
251
+ end
252
+
253
+ def play
254
+
255
+ loop do
256
+ board.render
257
+ player.take_turn
258
+ break if game_over?
259
+ end
260
+
261
+ endgame
262
+ end
263
+
264
+ private
265
+
266
+ def game_over?
267
+ board.victory? || board.game_lost?
268
+ end
269
+
270
+ def endgame
271
+ board.endgame_render
272
+ puts "Oh no! You touched a mine!" if board.game_lost?
273
+ puts "Congratulations! You won!" if board.victory?
274
+ puts "Thanks for playing!"
275
+ end
276
+ end
277
+
278
+
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'minesweeper/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "minesweeper"
8
+ spec.version = Minesweeper::VERSION
9
+ spec.authors = ["Michael Alexander"]
10
+ spec.email = ["alexandermw@gmail.com"]
11
+ spec.summary = %q{Minesweeper on the command line in Ruby, TDD-ed.}
12
+ spec.description = %q{Tests in Rspec}
13
+ spec.homepage = ""
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 "rspec", "~> 3.1.0"
24
+ spec.add_development_dependency "guard", "~> 4.5.0"
25
+ end
data/spec/.DS_Store ADDED
Binary file
@@ -0,0 +1,253 @@
1
+ require 'minesweeper'
2
+ require 'pry'
3
+
4
+ describe Game do
5
+ it 'should have a Player' do
6
+ expect(subject.player).to be_a Player
7
+ end
8
+
9
+ it 'should have a Board' do
10
+ expect(subject.board).to be_a Board
11
+ end
12
+
13
+ describe '#play' do
14
+ it 'should call player#take_turn' do
15
+ #necessary to avoid infinite loop
16
+ allow(subject.board).to receive(:victory?).and_return(true)
17
+ allow(subject.player).to receive(:take_turn)
18
+
19
+ expect(subject.player).to receive(:take_turn)
20
+ subject.play
21
+ end
22
+ it 'should call board#render' do
23
+ #avoid infinite loop
24
+ allow(subject.board).to receive(:victory?).and_return(true)
25
+ allow(subject.player).to receive(:take_turn)
26
+
27
+ expect(subject.board).to receive(:render).at_least(1).times
28
+ subject.play
29
+ end
30
+ end
31
+ end
32
+
33
+ describe Player do
34
+
35
+ #left as an exercise for the student
36
+
37
+ end
38
+
39
+ describe Board do
40
+
41
+ describe "#initialize" do
42
+
43
+ context 'with default options' do
44
+ it "should create a 10x10 array by default" do
45
+ expect(subject.size).to eq(10)
46
+ end
47
+
48
+ it "should have 9 mines by default" do
49
+ expect(subject.mine_count).to eq(9)
50
+ end
51
+
52
+ it 'should count adjacent mines up-front' do
53
+ expect( subject.grid.flatten.all? { |space| space.nearby_mines. is_a? Integer } ).to eq true
54
+ end
55
+
56
+ end
57
+
58
+
59
+ it 'should be an array' do
60
+ expect(subject.grid).to be_a Array
61
+ end
62
+
63
+ it 'should be an array of arrays' do
64
+ expect(subject.grid[0]).to be_a Array
65
+ end
66
+
67
+ # careful, this test has false positive if size is 0
68
+ it 'should be composed of spaces' do
69
+ expect(subject.grid.flatten.all? { |space| space.is_a? Space }).to eq true
70
+ end
71
+
72
+ it 'should have all Spaces be invisible at first' do
73
+ expect(subject.grid.flatten.all? {|s| !s.visible } ).to eq true
74
+ end
75
+
76
+ it 'should always be square' do
77
+ expect(subject.grid.size).to eq subject.grid[0].size
78
+ end
79
+
80
+ it 'can take a size up to 25' do
81
+ expect{Board.new(25)}.not_to raise_error
82
+ end
83
+
84
+ it 'creates 9 mines for a 10x10' do
85
+ expect(subject.mine_count).to eq 9
86
+ end
87
+
88
+ it 'creates 100 mines for a 25 x 25' do
89
+ expect( Board.new(25).mine_count ).to eq 100
90
+ end
91
+
92
+ it 'raises an error if inputs are not positive integers' do
93
+ expect{Board.new(-4)}.to raise_error
94
+ end
95
+
96
+ it 'raises an error if size are greater than 25' do
97
+ expect{Board.new(26)}.to raise_error
98
+ end
99
+
100
+ it 'should start with as many flags remaining as mines' do
101
+ expect(subject.flags_remaining).to eq(subject.mine_count)
102
+ end
103
+
104
+ end
105
+
106
+ describe '#render' do
107
+
108
+ end
109
+
110
+ describe '#place_flag' do
111
+ it 'should only be allowed if flags remain' do
112
+ allow(subject).to receive(:flags_remaining).and_return(0)
113
+ expect(subject.place_flag(0,0)).to eq(false)
114
+ end
115
+ it 'should only be valid on uncleared spaces' do
116
+ subject[0][0].mine = false
117
+ subject[0][0].visible = true
118
+
119
+ expect(subject.place_flag(0,0)).to eq(false)
120
+ end
121
+ it 'should decrement the flag counter by 1 if successful' do
122
+ flag_count = subject.flags_remaining
123
+ subject.place_flag(0,0)
124
+ expect(subject.flags_remaining).to eq (flag_count - 1)
125
+ end
126
+ it 'should change a space to appear flagged' do
127
+ subject.place_flag(0,0)
128
+ expect(subject[0][0].flagged).to eq true
129
+ end
130
+ end
131
+
132
+ describe '#mark_clear' do
133
+
134
+ it 'should change the space to visible' do
135
+ subject.mark_clear(0,0)
136
+ expect(subject[0][0].visible).to equal true
137
+ end
138
+
139
+ context 'if the space chosen is clear' do
140
+
141
+ #set up safe and unsafe spots
142
+ before(:each) do
143
+ subject[0][0].mine = false
144
+ subject[0][1].mine = false
145
+ subject[1][0].mine = false
146
+ subject[1][1].mine = true
147
+ end
148
+
149
+ it 'should not trigger a loss' do
150
+ expect(subject.game_lost?).to equal(false)
151
+ end
152
+ end
153
+
154
+ context 'if the space chosen has a mine' do
155
+ before(:each) do
156
+ subject[0][0].mine = true
157
+ end
158
+
159
+ it 'should trigger a loss' do
160
+ subject.mark_clear(0,0)
161
+ expect(subject.game_lost?).to equal true
162
+ end
163
+ end
164
+
165
+ context 'if the space has zero mines nearby' do
166
+
167
+ before(:each) do
168
+ subject.grid.flatten.each {|s| s.mine = false }
169
+ subject[3][3].nearby_mines = 0
170
+ end
171
+
172
+
173
+ # in a perfect world, we also want a test that checks
174
+ # if it keeps going forever. since that's a lot to mock out
175
+ # this test will stay around
176
+ it 'should uncover all adjacent mines' do
177
+
178
+ subject.mark_clear(3,3)
179
+
180
+ # whoa! you can iterate expectations!
181
+ # this way, the test fails if any one of these
182
+ # *NINE* expect clauses fail
183
+ 2.upto(4) do |x|
184
+ 2.upto(4) do |y|
185
+ expect(subject[x][y].visible).to equal true
186
+ end
187
+ end
188
+
189
+ end
190
+
191
+ end
192
+ end
193
+
194
+ describe '#victory?' do
195
+ it 'should be true when all non-mine spaces are visible' do
196
+ subject.grid.flatten.map! {|s| s.visible = true unless s.mine }
197
+ expect(subject.victory?).to equal true
198
+ end
199
+
200
+ it 'should be false otherwise' do
201
+ expect(subject.victory?).to equal false
202
+ end
203
+ end
204
+
205
+ describe '#game_lost?' do
206
+ it 'should be true as soon as a mine is marked as clear' do
207
+ subject[0][0].mine = true
208
+ subject.mark_clear(0,0)
209
+ expect(subject.game_lost?).to equal true
210
+ end
211
+
212
+ it 'should be false otherwise' do
213
+ expect(subject.game_lost?).to equal false
214
+ end
215
+ end
216
+
217
+ describe '#num_adjacent_mines' do
218
+ let(:single_mine){ Board.new }
219
+
220
+ before(:each) do
221
+ # this test board has a single mine only at 0, 0
222
+ single_mine.grid.flatten.each {|cell| cell.mine = false }
223
+ single_mine.grid[0][0].mine = true
224
+ end
225
+
226
+ it 'returns 0 when there are no mines next to a square' do
227
+ expect(single_mine.num_adjacent_mines(9,9)).to eq 0
228
+ end
229
+
230
+ it 'returns the number of mines next to a square' do
231
+ expect(single_mine.num_adjacent_mines(1,1)).to eq 1
232
+ end
233
+
234
+ end
235
+
236
+ end
237
+
238
+ describe Space do
239
+
240
+ describe '#initialize' do
241
+ it 'should start invisible' do
242
+ expect(subject.visible).to eq(false)
243
+ end
244
+
245
+ it 'should default to no mine' do
246
+ expect(subject.mine).to eq(false)
247
+ end
248
+
249
+ it 'should default to not flagged' do
250
+ expect(subject.flagged).to eq(false)
251
+ end
252
+ end
253
+ end
@@ -0,0 +1,89 @@
1
+ # This file was generated by the `rspec --init` command. Conventionally, all
2
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
3
+ # The generated `.rspec` file contains `--require spec_helper` which will cause this
4
+ # file to always be loaded, without a need to explicitly require it in any files.
5
+ #
6
+ # Given that it is always loaded, you are encouraged to keep this file as
7
+ # light-weight as possible. Requiring heavyweight dependencies from this file
8
+ # will add to the boot time of your test suite on EVERY test run, even for an
9
+ # individual file that may not need all of that loaded. Instead, consider making
10
+ # a separate helper file that requires the additional dependencies and performs
11
+ # the additional setup, and require it from the spec files that actually need it.
12
+ #
13
+ # The `.rspec` file also contains a few flags that are not defaults but that
14
+ # users commonly want.
15
+ #
16
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
17
+ RSpec.configure do |config|
18
+ # rspec-expectations config goes here. You can use an alternate
19
+ # assertion/expectation library such as wrong or the stdlib/minitest
20
+ # assertions if you prefer.
21
+ config.expect_with :rspec do |expectations|
22
+ # This option will default to `true` in RSpec 4. It makes the `description`
23
+ # and `failure_message` of custom matchers include text for helper methods
24
+ # defined using `chain`, e.g.:
25
+ # be_bigger_than(2).and_smaller_than(4).description
26
+ # # => "be bigger than 2 and smaller than 4"
27
+ # ...rather than:
28
+ # # => "be bigger than 2"
29
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
30
+ end
31
+
32
+ # rspec-mocks config goes here. You can use an alternate test double
33
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
34
+ config.mock_with :rspec do |mocks|
35
+ # Prevents you from mocking or stubbing a method that does not exist on
36
+ # a real object. This is generally recommended, and will default to
37
+ # `true` in RSpec 4.
38
+ mocks.verify_partial_doubles = true
39
+ end
40
+
41
+ # The settings below are suggested to provide a good initial experience
42
+ # with RSpec, but feel free to customize to your heart's content.
43
+ =begin
44
+ # These two settings work together to allow you to limit a spec run
45
+ # to individual examples or groups you care about by tagging them with
46
+ # `:focus` metadata. When nothing is tagged with `:focus`, all examples
47
+ # get run.
48
+ config.filter_run :focus
49
+ config.run_all_when_everything_filtered = true
50
+
51
+ # Limits the available syntax to the non-monkey patched syntax that is recommended.
52
+ # For more details, see:
53
+ # - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
54
+ # - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
55
+ # - http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3#new__config_option_to_disable_rspeccore_monkey_patching
56
+ config.disable_monkey_patching!
57
+
58
+ # This setting enables warnings. It's recommended, but in some cases may
59
+ # be too noisy due to issues in dependencies.
60
+ config.warnings = true
61
+
62
+ # Many RSpec users commonly either run the entire suite or an individual
63
+ # file, and it's useful to allow more verbose output when running an
64
+ # individual spec file.
65
+ if config.files_to_run.one?
66
+ # Use the documentation formatter for detailed output,
67
+ # unless a formatter has already been configured
68
+ # (e.g. via a command-line flag).
69
+ config.default_formatter = 'doc'
70
+ end
71
+
72
+ # Print the 10 slowest examples and example groups at the
73
+ # end of the spec run, to help surface which specs are running
74
+ # particularly slow.
75
+ config.profile_examples = 10
76
+
77
+ # Run specs in random order to surface order dependencies. If you find an
78
+ # order dependency and want to debug it, you can fix the order by providing
79
+ # the seed, which is printed after each run.
80
+ # --seed 1234
81
+ config.order = :random
82
+
83
+ # Seed global randomization in this process using the `--seed` CLI option.
84
+ # Setting this allows you to use `--seed` to deterministically reproduce
85
+ # test failures related to randomization by passing the same `--seed` value
86
+ # as the one that triggered the failure.
87
+ Kernel.srand config.seed
88
+ =end
89
+ end
data/test.rb ADDED
@@ -0,0 +1,11 @@
1
+ def count_between(arr, low, high)
2
+ counter = 0
3
+
4
+ arr.each do |element|
5
+ if (element >= low && element <= high)
6
+ counter++
7
+ end
8
+ end
9
+
10
+ return counter
11
+ end
metadata ADDED
@@ -0,0 +1,120 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: minesweeper
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Michael Alexander
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-01-26 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: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 3.1.0
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 3.1.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: 4.5.0
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 4.5.0
69
+ description: Tests in Rspec
70
+ email:
71
+ - alexandermw@gmail.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - ".DS_Store"
77
+ - ".gitignore"
78
+ - Gemfile
79
+ - Guardfile
80
+ - LICENSE.txt
81
+ - README.md
82
+ - Rakefile
83
+ - lib/.DS_Store
84
+ - lib/minesweeper.rb
85
+ - lib/minesweeper/.DS_Store
86
+ - lib/minesweeper/version.rb
87
+ - minesweeper.gemspec
88
+ - spec/.DS_Store
89
+ - spec/minesweeper_spec.rb
90
+ - spec/spec_helper.rb
91
+ - test.rb
92
+ homepage: ''
93
+ licenses:
94
+ - MIT
95
+ metadata: {}
96
+ post_install_message:
97
+ rdoc_options: []
98
+ require_paths:
99
+ - lib
100
+ required_ruby_version: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ required_rubygems_version: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ requirements: []
111
+ rubyforge_project:
112
+ rubygems_version: 2.4.2
113
+ signing_key:
114
+ specification_version: 4
115
+ summary: Minesweeper on the command line in Ruby, TDD-ed.
116
+ test_files:
117
+ - spec/.DS_Store
118
+ - spec/minesweeper_spec.rb
119
+ - spec/spec_helper.rb
120
+ has_rdoc: