xo 0.0.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/spec/xo/grid_spec.rb CHANGED
@@ -4,135 +4,231 @@ module XO
4
4
 
5
5
  describe Grid do
6
6
 
7
- it 'has 3 rows' do
7
+ it "defines X" do
8
+ Grid::X.must_equal :x
9
+ end
10
+
11
+ it "defines O" do
12
+ Grid::O.must_equal :o
13
+ end
14
+
15
+ it "has 3 rows" do
8
16
  Grid::ROWS.must_equal 3
9
17
  end
10
18
 
11
- it 'has 3 columns' do
19
+ it "has 3 columns" do
12
20
  Grid::COLS.must_equal 3
13
21
  end
14
22
 
15
- it 'contains all r, c where r is in {1, 2, 3} and c is in {1, 2, 3}' do
16
- (1..3).each do |r|
17
- (1..3).each do |c|
18
- Grid.contains?(r, c).must_equal true
23
+ it "has 9 positions" do
24
+ Grid::N.must_equal 9
25
+ end
26
+
27
+ describe ".contains?" do
28
+
29
+ it "contains all r, c where r is in {1, 2, 3} and c is in {1, 2, 3}" do
30
+ (1..3).each do |r|
31
+ (1..3).each do |c|
32
+ Grid.contains?(r, c).must_equal true
33
+ end
34
+ end
35
+ end
36
+
37
+ it "does not contain any r, c where either r is not in {1, 2, 3} or c is not in {1, 2, 3}" do
38
+ [[0, 0], [0, 1], [0, 2], [0, 3], [0, 4],
39
+ [1, 0], [1, 4],
40
+ [2, 0], [2, 4],
41
+ [3, 0], [3, 4],
42
+ [4, 0], [4, 1], [4, 2], [4, 3], [4, 4]].each do |pos|
43
+ Grid.contains?(*pos).must_equal false
44
+ end
45
+ end
46
+ end
47
+
48
+ describe ".is_token?" do
49
+
50
+ it "returns true for an X" do
51
+ Grid.is_token?(Grid::X).must_equal true
52
+ end
53
+
54
+ it "returns true for an O" do
55
+ Grid.is_token?(Grid::O).must_equal true
56
+ end
57
+
58
+ it "returns false otherwise" do
59
+ [nil, :e, '', ' '].each do
60
+ Grid.is_token?(:e).must_equal false
19
61
  end
20
62
  end
21
63
  end
22
64
 
23
- it 'does not contain any r, c where either r is not in {1, 2, 3} or c is not in {1, 2, 3}' do
24
- [[0, 0], [0, 1], [0, 2], [0, 3], [0, 4],
25
- [1, 0], [1, 4],
26
- [2, 0], [2, 4],
27
- [3, 0], [3, 4],
28
- [4, 0], [4, 1], [4, 2], [4, 3], [4, 4]].each do |pos|
29
- Grid.contains?(*pos).must_equal false
65
+ describe ".other_token" do
66
+
67
+ it "returns O given X" do
68
+ Grid.other_token(Grid::X).must_equal Grid::O
69
+ end
70
+
71
+ it "returns X given O" do
72
+ Grid.other_token(Grid::O).must_equal Grid::X
73
+ end
74
+
75
+ it "returns the same value it was given otherwise" do
76
+ Grid.other_token(:something_else).must_equal :something_else
30
77
  end
31
78
  end
32
79
 
33
80
  let(:grid) { Grid.new }
34
81
 
35
- describe 'a new grid' do
82
+ describe "an initial grid" do
36
83
 
37
- it 'is empty' do
84
+ it "is empty" do
38
85
  grid.empty?.must_equal true
39
86
  end
40
87
  end
41
88
 
42
- describe '#dup' do
89
+ describe "#new" do
43
90
 
44
- it 'creates a copy' do
45
- grid[1, 1] = X
91
+ it "can create a grid from a string" do
92
+ grid = Grid.new('xox o')
46
93
 
47
- grid_copy = grid.dup
48
- grid_copy[1, 1] = O
94
+ grid[1, 1].must_equal Grid::X
95
+ grid[1, 2].must_equal Grid::O
96
+ grid[1, 3].must_equal Grid::X
97
+ grid[2, 2].must_equal Grid::O
49
98
 
50
- grid[1, 1].must_equal X
99
+ [[2, 1], [2, 3], [3, 1], [3, 2], [3, 3]].each do |pos|
100
+ grid.open?(*pos).must_equal true
101
+ end
51
102
  end
52
- end
53
103
 
54
- describe '#empty?' do
104
+ it "only considers the first 9 characters" do
105
+ grid = Grid.new(' xoxoxoxox')
55
106
 
56
- it 'returns false when at least one position has a token' do
57
- grid[1, 1] = X
58
- grid.empty?.must_equal false
107
+ grid.empty?.must_equal true
108
+ end
109
+
110
+ it "can create a grid given exactly 9 characters" do
111
+ grid = Grid.new('xoxoxoxox')
112
+
113
+ grid.full?.must_equal true
59
114
  end
60
115
  end
61
116
 
62
- describe '#[]=' do
117
+ describe "#dup" do
118
+
119
+ it "creates a copy" do
120
+ grid[1, 1] = Grid::X
63
121
 
64
- it 'raises IndexError when a token is placed at a position it does not contain' do
65
- proc { grid[0, 0] = X }.must_raise IndexError
122
+ grid_copy = grid.dup
123
+ grid_copy[1, 1] = Grid::O
124
+
125
+ grid_copy[1, 1].must_equal Grid::O
126
+ grid[1, 1].must_equal Grid::X
66
127
  end
67
128
  end
68
129
 
69
- describe '#[]' do
130
+ describe "#empty?" do
70
131
 
71
- it 'raises IndexError when given a position it does not contain' do
72
- proc { grid[4, 4] }.must_raise IndexError
132
+ it "returns false when at least one position has a token" do
133
+ grid[1, 2] = Grid::X
134
+ grid.empty?.must_equal false
135
+ end
136
+
137
+ it "returns true otherwise" do
138
+ grid.empty?.must_equal true
73
139
  end
74
140
  end
75
141
 
76
- describe '#full?' do
142
+ describe "#full?" do
77
143
 
78
144
  before do
79
145
  (1..3).each do |r|
80
146
  (1..3).each do |c|
81
- grid[r, c] = O
147
+ grid[r, c] = Grid::O
82
148
  end
83
149
  end
84
150
  end
85
151
 
86
- it 'returns true when every position has a token' do
152
+ it "returns true when every position has a token" do
87
153
  grid.full?.must_equal true
88
154
  end
89
155
 
90
- it 'returns false when at least one position does not have a token' do
91
- grid[1, 1] = :e
156
+ it "returns false when at least one position doesn't have a token" do
157
+ grid[1, 3] = :e
92
158
  grid.full?.must_equal false
93
159
  end
94
160
  end
95
161
 
96
- describe '#free?' do
162
+ describe "#[]=" do
163
+
164
+ it "sets a position to X, O or :e" do
165
+ grid[2, 1] = Grid::X
166
+ grid[2, 1].must_equal Grid::X
167
+
168
+ grid[2, 2] = Grid::O
169
+ grid[2, 2].must_equal Grid::O
170
+
171
+ grid[2, 3] = :anything_else
172
+ grid[2, 3].must_equal :e
173
+ end
174
+
175
+ it "raises IndexError when the position is off the grid" do
176
+ proc { grid[0, 0] = Grid::X }.must_raise IndexError
177
+ end
178
+ end
179
+
180
+ describe "#[]" do
181
+
182
+ it "raises IndexError when the position is off the grid" do
183
+ proc { grid[4, 4] }.must_raise IndexError
184
+ end
185
+ end
186
+
187
+ describe "#open?" do
97
188
 
98
- it 'returns true when no token is at the given position' do
99
- grid.free?(2, 2).must_equal true
189
+ it "returns true when no token is at the given position" do
190
+ grid.open?(2, 2).must_equal true
100
191
  end
101
192
 
102
- it 'returns false when a token is at the given position' do
103
- grid[3, 1] = O
104
- grid.free?(3, 1).must_equal false
193
+ it "returns false when a token is at the given position" do
194
+ grid[2, 3] = Grid::O
195
+ grid.open?(2, 3).must_equal false
105
196
  end
106
197
 
107
- it 'raises IndexError when given a position the grid does not contain' do
108
- proc { grid.free?(0, 4) }.must_raise IndexError
198
+ it "raises IndexError when the position is off the grid" do
199
+ proc { grid.open?(0, 4) }.must_raise IndexError
109
200
  end
110
201
  end
111
202
 
112
- describe '#clear' do
203
+ describe "#clear" do
113
204
 
114
- it 'empties the grid' do
115
- grid[1, 1] = X
116
- grid[1, 3] = O
117
- grid[3, 2] = X
205
+ it "removes all tokens from the grid" do
206
+ grid[3, 1] = Grid::X
207
+ grid[3, 2] = Grid::O
208
+ grid[3, 3] = Grid::X
118
209
 
119
210
  grid.clear
120
211
 
121
212
  grid.empty?.must_equal true
122
213
  end
214
+
215
+ it "returns self" do
216
+ grid.clear.must_be_same_as grid
217
+ end
123
218
  end
124
219
 
125
- describe '#each' do
220
+ describe "#each" do
126
221
 
127
222
  it "visits every position and yields a block that takes the position's row, column and value" do
128
- grid[1, 1] = O
129
- grid[2, 2] = X
130
- grid[3, 3] = O
223
+ grid[1, 1] = Grid::O
224
+ grid[2, 2] = Grid::X
225
+ grid[3, 3] = Grid::O
131
226
 
132
227
  visited = {}
133
228
 
134
229
  grid.each do |r, c, val|
135
- # ensure that the value for the position is correct
230
+ # ensure that the position (r, c) is contained within the grid and
231
+ # ensure that the value at the position is correct
136
232
  grid[r, c].must_equal val
137
233
 
138
234
  # keep track of every position we visit
@@ -142,5 +238,52 @@ module XO
142
238
  visited.keys.size.must_equal(Grid::ROWS * Grid::COLS)
143
239
  end
144
240
  end
241
+
242
+ describe "#each_open" do
243
+
244
+ it "visits every open position and yields a block that takes the position's row and column" do
245
+ grid[1, 3] = Grid::X
246
+ grid[2, 2] = Grid::O
247
+ grid[3, 1] = Grid::X
248
+
249
+ visited = {}
250
+
251
+ grid.each_open do |r, c|
252
+ visited[[r, c]] = true
253
+ end
254
+
255
+ visited.keys.size.must_equal(Grid::ROWS * Grid::COLS - 3)
256
+
257
+ [[1, 1], [1, 2], [2, 1], [2, 3], [3, 2], [3, 3]].each do |pos|
258
+ visited.key?(pos)
259
+ end
260
+ end
261
+ end
262
+
263
+ describe "#inspect" do
264
+
265
+ it "returns a single line string representation of the grid" do
266
+ grid[1, 1] = grid[1, 3] = Grid::X
267
+ grid[1, 2] = grid[3, 3] = Grid::O
268
+
269
+ grid.inspect.must_equal "xox o"
270
+ end
271
+ end
272
+
273
+ describe "#to_s" do
274
+
275
+ it "returns a multiline string representation of the grid" do
276
+ grid[2, 1] = grid[2, 3] = Grid::X
277
+ grid[1, 2] = grid[2, 2] = Grid::O
278
+
279
+ grid.to_s.must_equal [
280
+ " | o | ",
281
+ "---+---+---",
282
+ " x | o | x ",
283
+ "---+---+---",
284
+ " | | "
285
+ ].join("\n")
286
+ end
287
+ end
145
288
  end
146
289
  end
data/xo.gemspec CHANGED
@@ -18,6 +18,13 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ['lib']
20
20
 
21
- spec.add_development_dependency 'rake', '~> 10.1', '>= 10.1.0'
22
- spec.add_development_dependency 'minitest', '~> 5.3', '>= 5.3.2'
21
+ spec.required_ruby_version = '>= 1.9.3'
22
+
23
+ spec.add_development_dependency 'rake', '~> 10.3'
24
+ spec.add_development_dependency 'minitest', '~> 5.3'
25
+ spec.add_development_dependency 'coveralls', '~> 0.7'
26
+
27
+ # For documentation
28
+ spec.add_development_dependency 'redcarpet', '~> 3.1'
29
+ spec.add_development_dependency 'yard', '~> 0.8'
23
30
  end
metadata CHANGED
@@ -1,77 +1,111 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: xo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dwayne R. Crooks
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-04-03 00:00:00.000000000 Z
11
+ date: 2014-05-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ~>
18
18
  - !ruby/object:Gem::Version
19
- version: '10.1'
20
- - - ">="
21
- - !ruby/object:Gem::Version
22
- version: 10.1.0
19
+ version: '10.3'
23
20
  type: :development
24
21
  prerelease: false
25
22
  version_requirements: !ruby/object:Gem::Requirement
26
23
  requirements:
27
- - - "~>"
28
- - !ruby/object:Gem::Version
29
- version: '10.1'
30
- - - ">="
24
+ - - ~>
31
25
  - !ruby/object:Gem::Version
32
- version: 10.1.0
26
+ version: '10.3'
33
27
  - !ruby/object:Gem::Dependency
34
28
  name: minitest
35
29
  requirement: !ruby/object:Gem::Requirement
36
30
  requirements:
37
- - - "~>"
31
+ - - ~>
38
32
  - !ruby/object:Gem::Version
39
33
  version: '5.3'
40
- - - ">="
41
- - !ruby/object:Gem::Version
42
- version: 5.3.2
43
34
  type: :development
44
35
  prerelease: false
45
36
  version_requirements: !ruby/object:Gem::Requirement
46
37
  requirements:
47
- - - "~>"
38
+ - - ~>
48
39
  - !ruby/object:Gem::Version
49
40
  version: '5.3'
50
- - - ">="
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.7'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '0.7'
55
+ - !ruby/object:Gem::Dependency
56
+ name: redcarpet
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
51
60
  - !ruby/object:Gem::Version
52
- version: 5.3.2
61
+ version: '3.1'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: '3.1'
69
+ - !ruby/object:Gem::Dependency
70
+ name: yard
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ~>
74
+ - !ruby/object:Gem::Version
75
+ version: '0.8'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ~>
81
+ - !ruby/object:Gem::Version
82
+ version: '0.8'
53
83
  description: A Ruby library that can be used to develop Tic-tac-toe game clients.
54
84
  email:
55
85
  - me@dwaynecrooks.com
56
- executables: []
86
+ executables:
87
+ - xo
57
88
  extensions: []
58
89
  extra_rdoc_files: []
59
90
  files:
60
- - ".gitignore"
91
+ - .gitignore
92
+ - .travis.yml
93
+ - Gemfile
94
+ - Gemfile.lock
61
95
  - LICENSE.txt
62
96
  - README.md
63
97
  - Rakefile
98
+ - bin/xo
64
99
  - lib/xo.rb
65
100
  - lib/xo/ai.rb
66
- - lib/xo/ai/advanced_beginner.rb
67
- - lib/xo/ai/expert.rb
101
+ - lib/xo/ai/geometric_grid.rb
68
102
  - lib/xo/ai/minimax.rb
69
- - lib/xo/ai/novice.rb
70
103
  - lib/xo/engine.rb
71
104
  - lib/xo/evaluator.rb
72
105
  - lib/xo/grid.rb
73
106
  - lib/xo/version.rb
74
107
  - spec/spec_helper.rb
108
+ - spec/xo/ai/geometric_grid_spec.rb
75
109
  - spec/xo/ai/minimax_spec.rb
76
110
  - spec/xo/engine_spec.rb
77
111
  - spec/xo/evaluator_spec.rb
@@ -87,12 +121,12 @@ require_paths:
87
121
  - lib
88
122
  required_ruby_version: !ruby/object:Gem::Requirement
89
123
  requirements:
90
- - - ">="
124
+ - - ! '>='
91
125
  - !ruby/object:Gem::Version
92
- version: '0'
126
+ version: 1.9.3
93
127
  required_rubygems_version: !ruby/object:Gem::Requirement
94
128
  requirements:
95
- - - ">="
129
+ - - ! '>='
96
130
  - !ruby/object:Gem::Version
97
131
  version: '0'
98
132
  requirements: []
@@ -103,7 +137,9 @@ specification_version: 4
103
137
  summary: A Ruby library for Tic-tac-toe.
104
138
  test_files:
105
139
  - spec/spec_helper.rb
140
+ - spec/xo/ai/geometric_grid_spec.rb
106
141
  - spec/xo/ai/minimax_spec.rb
107
142
  - spec/xo/engine_spec.rb
108
143
  - spec/xo/evaluator_spec.rb
109
144
  - spec/xo/grid_spec.rb
145
+ has_rdoc: