xo 0.0.1 → 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.
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: