tic_tac_toe_nhu 0.0.2 → 0.0.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b9d9d16f137592a3f7a289e6438f7f6da7cf3058
4
- data.tar.gz: 127b37245247e3bddbb54ac8f4470fa837041797
3
+ metadata.gz: ad5f41218a6c0fbe21ea418aae195ede891e00c8
4
+ data.tar.gz: 72979a92b1f8ffc400aa6ccd1d587c386ec3f4c6
5
5
  SHA512:
6
- metadata.gz: 7616a935a87c09b5b3031ed5e9de4f48c5cd949a088f881efdb51b0ae880600a4ccf63ef055302e46f1eab2896368a5dacfff50401f9a5da6d98e43921416de0
7
- data.tar.gz: 7f2886491f0f0acec8094d466120fddedfb202835052df2cbcf9ed1d82a688a4eb0bfdaaca10c5a6670ecfa7de93608dd5034c3627f01b1a4a922734294b60b8
6
+ metadata.gz: 96b3da857ffaf1e25cb8b76c62f547aebee2f5effbc5cc801649494b9aeb951f97efc83733cff092f6400002ed2b39d0c583fc419741b50a6931559801545251
7
+ data.tar.gz: fdc55c56a5a3c22da80712bcbb852f24806ffec263e37c8590b44957b87139ef0afd5dce96abf97762f763943eaae64e7dbdd1e3fbeeb421af04a498f795030b
@@ -1,107 +1,6 @@
1
1
  {
2
2
  "RSpec": {
3
3
  "coverage": {
4
- "/Users/nhunguyen/Documents/Ruby/tictactoe/lib/tic_tac_toe/board.rb": [
5
- 1,
6
- 1,
7
- null,
8
- null,
9
- 1,
10
- 1,
11
- null,
12
- 1,
13
- 119,
14
- 119,
15
- null,
16
- null,
17
- 1,
18
- 120,
19
- 120,
20
- 120,
21
- null,
22
- null,
23
- 1,
24
- 3380,
25
- 3377,
26
- 3377,
27
- null,
28
- 3,
29
- null,
30
- null,
31
- null,
32
- 1,
33
- 3070,
34
- null,
35
- null,
36
- 1,
37
- 2244,
38
- null,
39
- null,
40
- 1,
41
- 26,
42
- null,
43
- null,
44
- 1,
45
- 8643,
46
- 25929,
47
- null,
48
- null,
49
- null,
50
- 1,
51
- 8640,
52
- 8640,
53
- null,
54
- 233280,
55
- 25920,
56
- null,
57
- 8640,
58
- null,
59
- null,
60
- 1,
61
- 8640,
62
- 8640,
63
- 8640,
64
- null,
65
- null,
66
- 1,
67
- 3898,
68
- 3898,
69
- 35082,
70
- null,
71
- 3898,
72
- null,
73
- null,
74
- 1,
75
- 1,
76
- 38462,
77
- 38460,
78
- null,
79
- 9667,
80
- null,
81
- null,
82
- 1,
83
- 38462,
84
- 38461,
85
- 38460,
86
- null,
87
- null,
88
- 1,
89
- 38460,
90
- null,
91
- null,
92
- 1,
93
- 8640,
94
- 77760,
95
- null,
96
- 8640,
97
- null,
98
- null,
99
- 1,
100
- 86400,
101
- null,
102
- null,
103
- null
104
- ],
105
4
  "/Users/nhunguyen/Documents/Ruby/tictactoe/lib/tic_tac_toe/game_factory.rb": [
106
5
  1,
107
6
  1,
@@ -110,11 +9,11 @@
110
9
  1,
111
10
  1,
112
11
  1,
113
- 11,
12
+ 13,
114
13
  null,
115
14
  null,
116
15
  1,
117
- 4,
16
+ 6,
118
17
  null,
119
18
  null,
120
19
  1,
@@ -135,26 +34,22 @@
135
34
  1,
136
35
  1,
137
36
  1,
138
- 1,
139
- 1,
140
37
  null,
141
38
  null,
142
39
  1,
143
40
  2,
144
- 2,
145
- 2,
146
41
  null,
147
42
  null,
148
43
  1,
149
44
  1,
150
- 1,
151
- 1,
152
45
  null,
153
46
  null,
154
47
  1,
155
48
  1,
49
+ null,
50
+ null,
156
51
  1,
157
- 1,
52
+ 5,
158
53
  null,
159
54
  null,
160
55
  null
@@ -202,216 +97,40 @@
202
97
  null,
203
98
  null
204
99
  ],
205
- "/Users/nhunguyen/Documents/Ruby/tictactoe/lib/tic_tac_toe/rules.rb": [
206
- 1,
207
- 1,
208
- 1,
209
- 73,
210
- null,
211
- null,
212
- 1,
213
- 3080,
214
- 1922,
215
- 1605,
216
- null,
217
- null,
218
- 1,
219
- 321,
220
- null,
221
- null,
222
- 1,
223
- 13528,
224
- null,
225
- null,
226
- 1,
227
- 1,
228
- 8638,
229
- 164366,
230
- null,
231
- null,
232
- null,
233
- 1,
234
- 8638,
235
- null,
236
- null,
237
- null
238
- ],
239
- "/Users/nhunguyen/Documents/Ruby/tictactoe/lib/tic_tac_toe/player_factory.rb": [
240
- 1,
241
- 1,
242
- 1,
243
- null,
244
- 1,
245
- 1,
246
- null,
247
- 1,
248
- 4,
249
- null,
250
- null,
251
- 1,
252
- 4,
253
- 4,
254
- null,
255
- null,
256
- null
257
- ],
258
- "/Users/nhunguyen/Documents/Ruby/tictactoe/lib/tic_tac_toe/strategy/minimax.rb": [
259
- 1,
260
- null,
261
- 1,
262
- 1,
263
- 1,
264
- 1,
265
- 27,
266
- 27,
267
- 27,
268
- 27,
269
- null,
270
- null,
271
- 1,
272
- 23,
273
- 3,
274
- null,
275
- 20,
276
- 20,
277
- null,
278
- null,
279
- null,
280
- 1,
281
- 1,
282
- 1,
283
- 1,
284
- 1,
285
- null,
286
- 1,
287
- 23,
288
- 23,
289
- null,
290
- null,
291
- 1,
292
- 3,
293
- 1,
294
- null,
295
- null,
296
- 1,
297
- 1620,
298
- 1620,
299
- 3068,
300
- 3068,
301
- 3068,
302
- 3068,
303
- null,
304
- 1620,
305
- null,
306
- null,
307
- 1,
308
- 3068,
309
- 1468,
310
- null,
311
- 1600,
312
- 1600,
313
- null,
314
- null,
315
- null,
316
- 1,
317
- 3068,
318
- null,
319
- null,
320
- 1,
321
- 1468,
322
- 1468,
323
- 320,
324
- 317,
325
- null,
326
- null,
327
- null,
328
- null,
329
- 1,
330
- 1920,
331
- null,
332
- null,
333
- 1,
334
- 3227,
335
- 4688,
336
- null,
337
- null,
338
- null,
339
- 1,
340
- null,
341
- null
342
- ],
343
- "/Users/nhunguyen/Documents/Ruby/tictactoe/lib/tic_tac_toe/strategy/console_user.rb": [
344
- 1,
345
- 1,
346
- 1,
347
- null,
348
- 1,
349
- 7,
350
- 7,
351
- null,
352
- null,
100
+ "/Users/nhunguyen/Documents/Ruby/tictactoe/lib/tic_tac_toe/main.rb": [
353
101
  1,
354
- 3,
355
- null,
356
- 3,
357
- 5,
358
- 5,
359
- null,
360
- null,
361
- 3,
362
- null,
363
- null,
364
102
  1,
365
103
  1,
366
104
  null,
367
- null,
368
- null,
369
- null
370
- ],
371
- "/Users/nhunguyen/Documents/Ruby/tictactoe/lib/tic_tac_toe/player.rb": [
372
105
  1,
373
106
  1,
374
107
  1,
375
108
  null,
376
109
  1,
377
- 50,
378
- 50,
379
- 50,
110
+ 12,
111
+ 12,
112
+ 12,
380
113
  null,
381
114
  null,
382
115
  1,
383
- 5,
116
+ 12,
117
+ 12,
118
+ 12,
119
+ 12,
120
+ 12,
384
121
  null,
385
122
  null,
386
- null
387
- ],
388
- "/Users/nhunguyen/Documents/Ruby/tictactoe/lib/tic_tac_toe/main.rb": [
389
- 1,
390
- 1,
391
- 1,
392
- null,
393
123
  1,
394
124
  1,
125
+ 13,
126
+ 13,
127
+ 13,
395
128
  1,
396
- null,
397
- 1,
398
- 14,
399
- 14,
400
- 14,
401
- null,
402
- null,
403
129
  1,
404
- 11,
405
- 11,
406
- 11,
407
130
  null,
408
- 11,
409
- 11,
410
- 11,
411
131
  null,
412
132
  null,
413
133
  1,
414
- 1,
415
134
  7,
416
135
  7,
417
136
  7,
@@ -423,9 +142,9 @@
423
142
  null,
424
143
  null,
425
144
  1,
145
+ 12,
146
+ 12,
426
147
  11,
427
- 11,
428
- 10,
429
148
  null,
430
149
  1,
431
150
  null,
@@ -441,8 +160,8 @@
441
160
  1,
442
161
  null,
443
162
  1,
444
- 13,
445
- 13,
163
+ 14,
164
+ 14,
446
165
  null,
447
166
  null,
448
167
  1,
@@ -454,10 +173,14 @@
454
173
  null,
455
174
  null,
456
175
  1,
457
- 3,
458
- 3,
459
- 3,
460
- 3,
176
+ 5,
177
+ 5,
178
+ 5,
179
+ 5,
180
+ 4,
181
+ null,
182
+ 1,
183
+ null,
461
184
  null,
462
185
  null,
463
186
  1,
@@ -487,16 +210,25 @@
487
210
  null,
488
211
  null,
489
212
  1,
490
- 3,
491
- 3,
492
- 12,
213
+ 5,
214
+ 5,
215
+ 20,
493
216
  null,
494
- 3,
217
+ 5,
218
+ null,
219
+ null,
220
+ 1,
221
+ 20,
222
+ null,
223
+ null,
224
+ 1,
225
+ 40,
226
+ 20,
495
227
  null,
496
228
  null,
497
229
  null
498
230
  ]
499
231
  },
500
- "timestamp": 1372702698
232
+ "timestamp": 1374084056
501
233
  }
502
234
  }
@@ -21,7 +21,7 @@ module TicTacToe
21
21
  squares[move] = value
22
22
  @unique_marked_values << value if !@unique_marked_values.include?(value)
23
23
  else
24
- raise MoveNotAvailableError
24
+ raise MoveNotAvailableError.new("#{value} is trying to move at #{move}. available_moves: #{available_moves.inspect}")
25
25
  end
26
26
  end
27
27
 
@@ -67,6 +67,14 @@ module TicTacToe
67
67
  result
68
68
  end
69
69
 
70
+ def clone
71
+ board_copy = self.class.new
72
+ squares.each_with_index do |value, index|
73
+ board_copy.mark(index, value) if value
74
+ end
75
+ board_copy
76
+ end
77
+
70
78
  private
71
79
  def move_available?(move)
72
80
  return false if out_of_range?(move)
@@ -78,7 +86,6 @@ module TicTacToe
78
86
  def out_of_range?(move)
79
87
  return true if move < 0
80
88
  return true if move >= squares.size
81
- return false
82
89
  end
83
90
 
84
91
  def marked?(move)
@@ -9,7 +9,7 @@ module TicTacToe
9
9
  end
10
10
 
11
11
  def types
12
- ["You vs Computer", "Computer vs You", "You vs Friend", "Computer vs Computer"]
12
+ [[:human, :computer], [:computer, :human], [:human, :human], [:computer, :computer]]
13
13
  end
14
14
 
15
15
  def create(type_index, board)
@@ -29,27 +29,23 @@ module TicTacToe
29
29
 
30
30
  private
31
31
  def computer_human_game(board)
32
- computer = @player_factory.computer(board)
33
- human = @player_factory.human
34
- TicTacToe::Game.new(board, computer, human)
32
+ create_game(board, @player_factory.computer(board), @player_factory.human)
35
33
  end
36
34
 
37
35
  def human_computer_game(board)
38
- computer = @player_factory.computer(board)
39
- human = @player_factory.human
40
- TicTacToe::Game.new(board, human, computer)
36
+ create_game(board, @player_factory.human, @player_factory.computer(board))
41
37
  end
42
38
 
43
39
  def human_human_game(board)
44
- human1 = @player_factory.human
45
- human2 = @player_factory.human("Friend", "O")
46
- TicTacToe::Game.new(board, human1, human2)
40
+ create_game(board, @player_factory.human, @player_factory.human("Friend", "O"))
47
41
  end
48
42
 
49
43
  def computer_computer_game(board)
50
- computer1 = @player_factory.computer(board, "X", "O")
51
- computer2 = @player_factory.computer(board, "O", "X")
52
- TicTacToe::Game.new(board, computer1, computer2)
44
+ create_game(board, @player_factory.computer(board, "X", "O"), @player_factory.computer(board, "O", "X"))
45
+ end
46
+
47
+ def create_game(board, player1, player2)
48
+ TicTacToe::Game.new(board, player1, player2)
53
49
  end
54
50
  end
55
51
  end
@@ -14,15 +14,22 @@ module TicTacToe
14
14
 
15
15
  def start
16
16
  @ui.display_welcome_message
17
- game_type = @ui.game_type
18
- @game = @game_factory.create(game_type, @board)
19
-
17
+ @game = create_game
20
18
  play until @game.over?
21
19
  @ui.display_board(@board)
22
20
  display_result
23
21
  end
24
22
 
25
23
  private
24
+ def create_game
25
+ game_type = @ui.game_type
26
+ begin
27
+ @game_factory.create(game_type, @board)
28
+ rescue ArgumentError
29
+ create_game
30
+ end
31
+ end
32
+
26
33
  def play
27
34
  @ui.display_board(@board)
28
35
  player = @game.current_player
@@ -7,16 +7,12 @@ module TicTacToe
7
7
  @board = board
8
8
  @player = player
9
9
  @opponent = opponent
10
- @rules = TicTacToe::Rules.new(@board)
11
10
  end
12
11
 
13
12
  def move
14
- if first_move?
15
- first_move
16
- else
17
- move = minimax(@player)
18
- move.move
19
- end
13
+ return first_move if first_move?
14
+ move = minimax(@player, @board)
15
+ move.move
20
16
  end
21
17
 
22
18
  private
@@ -35,22 +31,22 @@ module TicTacToe
35
31
  0
36
32
  end
37
33
 
38
- def minimax(player)
34
+ def minimax(player, board)
39
35
  moves = []
40
- @board.available_moves.each do |move|
41
- @board.mark(move, player)
42
- moves << player_move(player, move)
43
- @board.clear(move)
36
+ board.available_moves.each do |move|
37
+ clone_board = board.clone
38
+ clone_board.mark(move, player)
39
+ moves << player_move(player, move, clone_board)
44
40
  found_best_move?(moves[-1])
45
41
  end
46
42
  best_move(moves)
47
43
  end
48
44
 
49
- def player_move(player, move)
50
- if @rules.game_over?
51
- PlayerMove.new(move, score(player), 0)
45
+ def player_move(player, move, board)
46
+ if rules(board).game_over?
47
+ PlayerMove.new(move, score(player, board), 0)
52
48
  else
53
- child_move = minimax(opponent(player))
49
+ child_move = minimax(opponent(player), board)
54
50
  PlayerMove.new(move, -child_move.score, child_move.depth += 1)
55
51
  end
56
52
  end
@@ -59,13 +55,11 @@ module TicTacToe
59
55
  move.score == WINNING_SCORE and move.depth == 0
60
56
  end
61
57
 
62
- def score(player)
63
- winner = @rules.winner
58
+ def score(player, board)
59
+ winner = rules(board).winner
64
60
  return WINNING_SCORE if winner == player
65
61
  return LOSING_SCORE if winner == opponent(player)
66
- return TIE if @rules.tied?
67
-
68
- nil
62
+ return TIE if rules(board).tied?
69
63
  end
70
64
 
71
65
  def opponent(player)
@@ -76,6 +70,10 @@ module TicTacToe
76
70
  sorted_moves = moves.sort{ |a, b| [a.score, a.depth] <=> [b.score, b.depth]}
77
71
  sorted_moves.max_by {|m| m.score}
78
72
  end
73
+
74
+ def rules(board)
75
+ TicTacToe::Rules.new(board)
76
+ end
79
77
  end
80
78
 
81
79
  PlayerMove = Struct.new(:move, :score, :depth)
@@ -17,10 +17,14 @@ module TicTacToe
17
17
  end
18
18
 
19
19
  def game_type
20
- @output.puts("Please select a game type.")
20
+ @output.puts("Please enter a game type from the list.")
21
21
  @output.puts(game_type_list)
22
22
  type = @input.gets
23
- type.to_i
23
+ if type =~ /\d/
24
+ type.to_i
25
+ else
26
+ game_type
27
+ end
24
28
  end
25
29
 
26
30
  def display_winner(winner)
@@ -28,7 +32,7 @@ module TicTacToe
28
32
  end
29
33
 
30
34
  def display_tied_game
31
- @output.puts("It's a tied!")
35
+ @output.puts("Tied!")
32
36
  end
33
37
 
34
38
  def display_square_not_available
@@ -52,9 +56,18 @@ module TicTacToe
52
56
  def game_type_list
53
57
  result = ""
54
58
  TicTacToe::GameFactory.new.types.each_with_index do |value, index|
55
- result << "#{index + 1} - #{value}\n"
59
+ result << "#{index + 1} - #{game_type_values(value)}\n"
56
60
  end
57
61
  result
58
62
  end
63
+
64
+ def game_type_values(types)
65
+ "#{player_type(types[0])} vs #{player_type(types[1])}"
66
+ end
67
+
68
+ def player_type(type)
69
+ return "Human" if type == :human
70
+ return "Computer" if type == :computer
71
+ end
59
72
  end
60
73
  end
@@ -1,7 +1,4 @@
1
- $LOAD_PATH << File.expand_path('../../lib', __FILE__)
2
- require 'tic_tac_toe'
3
- require 'tic_tac_toe/mock/player'
1
+ describe "all situations" do
4
2
 
5
- player = MockPlayer.new([8, 6, 3])
6
- game = TicTacToe::GameFactory.computer_user_game
7
- game.start
3
+
4
+ end
@@ -0,0 +1,58 @@
1
+ require 'tic_tac_toe/board'
2
+ require 'tic_tac_toe/rules'
3
+ require 'tic_tac_toe/player_factory'
4
+
5
+ class SimpleStrategy
6
+ attr_accessor :next_move
7
+
8
+ def move
9
+ next_move
10
+ end
11
+ end
12
+
13
+ describe "Unbeatable computer", :slow_test => true do
14
+ before(:each) do
15
+ @board = TicTacToe::Board.new
16
+ @human_value = "X"
17
+ end
18
+
19
+ it "wins all game when computer goes first" do
20
+ make_computer_move(@board)
21
+ make_move(@board, [])
22
+ end
23
+
24
+ it "wins all game when human goes first" do
25
+ make_move(@board, [])
26
+ end
27
+
28
+ def make_computer_move(clone_board)
29
+ computer = TicTacToe::PlayerFactory.new.computer(clone_board)
30
+ clone_board.mark(computer.move, computer.value)
31
+ clone_board
32
+ end
33
+
34
+ def rules(board)
35
+ TicTacToe::Rules.new(board)
36
+ end
37
+
38
+ def make_move(board, move_history)
39
+ if rules(board).game_over?
40
+ print "."
41
+ if rules(board).winner == @human_value
42
+ print move_history
43
+ raise "Human wins."
44
+ end
45
+ else
46
+ board.available_moves.each do |move|
47
+ move_history << move
48
+ cloned_board = board.clone
49
+ cloned_board.mark(move, "X")
50
+ make_computer_move(cloned_board) if !rules(cloned_board).game_over?
51
+ make_move(cloned_board, move_history)
52
+ move_history.delete(move)
53
+ end
54
+ end
55
+ end
56
+
57
+
58
+ end
data/spec/mocks/game.rb CHANGED
@@ -9,3 +9,9 @@ class MockGame
9
9
  define :winner
10
10
  define(:over?){true}
11
11
  end
12
+
13
+ describe TicTacToe::Game do
14
+ it "checks MockGame" do
15
+ MockGame.should be_substitutable_for(TicTacToe::Game)
16
+ end
17
+ end
@@ -6,3 +6,9 @@ class MockGameFactory
6
6
  define :types
7
7
  define(:create) {|type, board|}
8
8
  end
9
+
10
+ describe TicTacToe::GameFactory do
11
+ it "checks game factory" do
12
+ MockGameFactory.should be_substitutable_for(TicTacToe::GameFactory)
13
+ end
14
+ end
@@ -6,3 +6,9 @@ class MockPlayerFactory
6
6
  define(:human) {|name = "Sue", value = "X"|}
7
7
  define(:computer) {|board, value = "X", opponent="O"|}
8
8
  end
9
+
10
+ describe TicTacToe::PlayerFactory do
11
+ it "checks mock player" do
12
+ MockPlayerFactory.should be_substitutable_for(TicTacToe::PlayerFactory)
13
+ end
14
+ end
data/spec/mocks/rules.rb CHANGED
@@ -7,3 +7,9 @@ class MockRules
7
7
  define(:tied?)
8
8
  define(:winner)
9
9
  end
10
+
11
+ describe TicTacToe::Rules do
12
+ it "checks if mock rules is substitutable" do
13
+ MockRules.should be_substitutable_for(TicTacToe::Rules)
14
+ end
15
+ end
@@ -13,3 +13,9 @@ class MockConsole
13
13
  define :display_square_not_available
14
14
  define(:display_player_turn) {|player|}
15
15
  end
16
+
17
+ describe TicTacToe::Console do
18
+ it "checks console" do
19
+ MockConsole.should be_substitutable_for(TicTacToe::Console)
20
+ end
21
+ end
@@ -165,7 +165,7 @@ describe TicTacToe::Board do
165
165
  it "returns two marks when two user marks the board" do
166
166
  @board.mark(4, "X")
167
167
  @board.mark(0, "O")
168
- @board.unique_marked_values.should == ["X", "O"]
168
+ @board.unique_marked_values.should =~ ["X", "O"]
169
169
  end
170
170
 
171
171
  it "returns one mark even though user marks the board twice" do
@@ -176,6 +176,30 @@ describe TicTacToe::Board do
176
176
 
177
177
  end
178
178
 
179
+ describe "creating a copy of the board" do
180
+ it "is marked on the copy when the original is marked" do
181
+ @board.mark(4, "X")
182
+ board_copy = @board.clone
183
+
184
+ board_copy.available_moves.should_not include(4)
185
+ end
186
+
187
+ it "is unaffected by changes to the original" do
188
+ @board.mark(4, "X")
189
+ board_copy = @board.clone
190
+ @board.mark(5, "O")
191
+
192
+ board_copy.available_moves.should include(5)
193
+ end
194
+
195
+ it "marks the actual value" do
196
+ @board.mark(4, "X")
197
+ board_copy = @board.clone
198
+
199
+ board_copy.unique_marked_values.should == ["X"]
200
+ end
201
+ end
202
+
179
203
  def mark_all_squares
180
204
  (0...@size**2).each {|position| @board.mark(position, @player)}
181
205
  end
@@ -8,38 +8,38 @@ describe TicTacToe::Game do
8
8
  before(:each) do
9
9
  @board = TicTacToe::Board.new
10
10
 
11
- @todd_strategy = MockDynamicStrategy.new
12
- @todd = TicTacToe::Player.new("Todd", "X", @todd_strategy)
11
+ @player1_strategy = MockDynamicStrategy.new
12
+ @player1 = TicTacToe::Player.new("Todd", "X", @player1_strategy)
13
13
 
14
- @john_strategy = MockDynamicStrategy.new
15
- @john = TicTacToe::Player.new("John", "O", @john_strategy)
14
+ @player2_strategy = MockDynamicStrategy.new
15
+ @player2 = TicTacToe::Player.new("John", "O", @player2_strategy)
16
16
 
17
- @game = TicTacToe::Game.new(@board, @todd, @john)
17
+ @game = TicTacToe::Game.new(@board, @player1, @player2)
18
18
  end
19
19
 
20
20
  context "marking board" do
21
21
  it "mark the board with user input" do
22
- @todd_strategy.add_move(1)
22
+ @player1_strategy.add_move(1)
23
23
  @game.make_move
24
- @board.unique_marked_values.should include(@todd.value)
24
+ @board.unique_marked_values.should include(@player1.value)
25
25
  end
26
26
 
27
27
  it "does not mark the board if user doesn't return an input" do
28
- @todd_strategy.add_move(nil)
28
+ @player1_strategy.add_move(nil)
29
29
  @game.make_move
30
- @board.unique_marked_values.should_not include(@todd.value)
30
+ @board.unique_marked_values.should_not include(@player1.value)
31
31
  end
32
32
  end
33
33
 
34
34
  describe "return winner player based on the value return from rules" do
35
35
  it "is Todd when value is X" do
36
- mark_board([0, 1, 2], @todd.value)
37
- @game.winner.should == @todd
36
+ mark_board([0, 1, 2], @player1.value)
37
+ @game.winner.should == @player1
38
38
  end
39
39
 
40
40
  it "is John when it is O" do
41
- mark_board([0, 1, 2], @john.value)
42
- @game.winner.should == @john
41
+ mark_board([0, 1, 2], @player2.value)
42
+ @game.winner.should == @player2
43
43
  end
44
44
 
45
45
  it "is nil when no one wins" do
@@ -49,25 +49,25 @@ describe TicTacToe::Game do
49
49
 
50
50
  describe "changes player" do
51
51
  it "doesn't change player if player 1 doesn't return a move" do
52
- @game.current_player.should == @todd
53
- @todd_strategy.add_move(nil)
52
+ @game.current_player.should == @player1
53
+ @player1_strategy.add_move(nil)
54
54
 
55
55
  @game.make_move
56
- @game.current_player.should == @todd
56
+ @game.current_player.should == @player1
57
57
  end
58
58
 
59
59
  it "changes to player 2 after player 1 moves" do
60
- @game.current_player.should == @todd
61
- @todd_strategy.add_move(1)
60
+ @game.current_player.should == @player1
61
+ @player1_strategy.add_move(1)
62
62
 
63
63
  @game.make_move
64
- @game.current_player.should == @john
64
+ @game.current_player.should == @player2
65
65
  end
66
66
  end
67
67
 
68
68
  describe "game over" do
69
69
  it "is over when there is a winner" do
70
- mark_board([0, 1, 2], @john.value)
70
+ mark_board([0, 1, 2], @player2.value)
71
71
  @game.should be_over
72
72
  end
73
73
 
@@ -81,11 +81,42 @@ describe TicTacToe::Game do
81
81
  end
82
82
 
83
83
  it "is not over when there is no winner or a tied" do
84
- mark_board([1, 2], @todd.value)
84
+ mark_board([1, 2], @player1.value)
85
85
  @game.should_not be_over
86
86
  end
87
87
  end
88
88
 
89
+ # describe "a copy of the game" do
90
+ # it "has the same current player" do
91
+ # @player1_strategy.add_move(1)
92
+ # @game.make_move
93
+ # @game.clone.current_player.should == @game.current_player
94
+ # end
95
+ #
96
+ # it "has the same moves previously made" do
97
+ # @player1_strategy.add_move(1)
98
+ # @game.make_move
99
+ # @game.clone.board.available_moves.should_not include(1)
100
+ # end
101
+ #
102
+ # it "has the current player unaffected by changes to the original game" do
103
+ # clone_game = @game.clone
104
+ # @player1_strategy.add_move(1)
105
+ # @game.make_move
106
+ #
107
+ # clone_game.current_player.should == @player1
108
+ # @game.current_player.should == @player2
109
+ # end
110
+ #
111
+ # it "clones the board" do
112
+ # clone_game = @game.clone
113
+ # @player1_strategy.add_move(1)
114
+ # @game.make_move
115
+ #
116
+ # @game.board.available_moves.should_not include(1)
117
+ # clone_game.board.available_moves.should include(1)
118
+ # end
119
+ # end
89
120
  def mark_board(moves, value)
90
121
  moves.each do |m|
91
122
  @board.mark(m, value)
@@ -19,20 +19,6 @@ describe TicTacToe::Main do
19
19
  @controller = TicTacToe::Main.new(@ui, @game_factory)
20
20
  end
21
21
 
22
- context "ensure mock class has the same interface" do
23
- it "checks MockGame" do
24
- MockGame.should be_substitutable_for(TicTacToe::Game)
25
- end
26
-
27
- it "checks console" do
28
- MockConsole.should be_substitutable_for(TicTacToe::Console)
29
- end
30
-
31
- it "checks game factory" do
32
- MockGameFactory.should be_substitutable_for(TicTacToe::GameFactory)
33
- end
34
- end
35
-
36
22
  describe "starts game" do
37
23
  it "displays welcome message" do
38
24
  @controller.start
@@ -48,6 +34,11 @@ describe TicTacToe::Main do
48
34
  @controller.start
49
35
  @game_factory.was told_to(:create)
50
36
  end
37
+
38
+ it "asks ui for game type again if the input is incorrect" do
39
+ @game_factory.will_create ArgumentError.new, @game
40
+ @controller.start
41
+ end
51
42
  end
52
43
 
53
44
  describe "play game" do
@@ -1,6 +1,6 @@
1
1
  require 'tic_tac_toe/spec_helper'
2
2
  require 'tic_tac_toe/player'
3
- require 'tic_tac_toe/strategy/mock'
3
+ require 'mocks/strategy/dynamic'
4
4
 
5
5
  describe TicTacToe::Player do
6
6
 
@@ -18,13 +18,13 @@ describe TicTacToe::Player do
18
18
 
19
19
  it "gets player's move" do
20
20
  move = 4
21
- strategy = MockStrategy.new([4])
21
+ strategy = MockDynamicStrategy.new([4])
22
22
  player = TicTacToe::Player.new(nil, nil, strategy)
23
23
  player.move.should == move
24
24
  end
25
25
 
26
26
  it "gets strategy" do
27
- strategy = MockStrategy.new([4])
27
+ strategy = MockDynamicStrategy.new([4])
28
28
  player = TicTacToe::Player.new(nil, nil, strategy)
29
29
  player.strategy.should == strategy
30
30
 
@@ -50,14 +50,14 @@ describe TicTacToe::Console do
50
50
 
51
51
  context "reading user input for game type" do
52
52
  it "displays a list of game type" do
53
- expected_display = "1 - You vs Computer\n2 - Computer vs You\n3 - You vs Friend"
53
+ expected_display = "1 - Human vs Computer\n2 - Computer vs Human\n3 - Human vs Human\n4 - Computer vs Computer"
54
54
  @input.string = "1"
55
55
  @console.game_type
56
56
  @output.string.should match expected_display
57
57
  end
58
58
 
59
59
  it "displays a message asking user to select a game type" do
60
- expected_display = "Please select a game type."
60
+ expected_display = "Please enter a game type from the list."
61
61
  @input.string = "1"
62
62
  @console.game_type
63
63
  @output.string.should match expected_display
@@ -67,6 +67,13 @@ describe TicTacToe::Console do
67
67
  @input.string = "1"
68
68
  @console.game_type.should == 1
69
69
  end
70
+
71
+ it "asks for user input again when user enter a character" do
72
+ expected_display = "Please enter a game type from the list."
73
+ @input.should_receive(:gets).twice.and_return("a", "1")
74
+ @console.game_type
75
+ @output.string.should match expected_display
76
+ end
70
77
  end
71
78
 
72
79
  it "displays winner" do
@@ -77,7 +84,7 @@ describe TicTacToe::Console do
77
84
 
78
85
  it "display tied game" do
79
86
  @console.display_tied_game
80
- @output.string.should == "It's a tied!\n"
87
+ @output.string.should == "Tied!\n"
81
88
  end
82
89
 
83
90
  it "displays square is not available" do
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'tic_tac_toe_nhu'
3
- s.version = '0.0.2'
3
+ s.version = '0.0.3'
4
4
  s.date = '2013-06-11'
5
5
  s.summary = "Tic Tac Toe"
6
6
  s.description = "A simple tic tac toe game with AI"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tic_tac_toe_nhu
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nhu Nguyen
@@ -40,6 +40,7 @@ files:
40
40
  - lib/tic_tac_toe/strategy/minimax.rb
41
41
  - lib/tic_tac_toe/ui/console.rb
42
42
  - spec/integration/tictactoe/tic_tac_toe.rb
43
+ - spec/integration/tictactoe/unbeatable_computer_spec.rb
43
44
  - spec/mocks/game.rb
44
45
  - spec/mocks/game_factory.rb
45
46
  - spec/mocks/player_factory.rb
@@ -57,7 +58,6 @@ files:
57
58
  - spec/tic_tac_toe/spec_helper.rb
58
59
  - spec/tic_tac_toe/strategy/console_user_spec.rb
59
60
  - spec/tic_tac_toe/strategy/minimax_spec.rb
60
- - spec/tic_tac_toe/strategy/mock.rb
61
61
  - spec/tic_tac_toe/ui/console_spec.rb
62
62
  - tic_tac_toe_nhu.gemspec
63
63
  homepage: http://rubygems.org/gems/tic_tac_toe_nhu
@@ -1,19 +0,0 @@
1
- class MockStrategy
2
- attr_accessor :moves
3
-
4
- def initialize(moves = [])
5
- @moves = moves
6
- end
7
-
8
- def add_move(move)
9
- @moves << move
10
- end
11
-
12
- def move
13
- @moves.shift
14
- end
15
-
16
- def needs_input?
17
- true
18
- end
19
- end