tic_tac_toe_nhu 0.0.5 → 0.0.11

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.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/bin/tic_tac_toe +3 -3
  3. data/coverage/.last_run.json +1 -1
  4. data/coverage/.resultset.json +135 -51
  5. data/lib/tic_tac_toe/board.rb +1 -1
  6. data/lib/tic_tac_toe/game.rb +23 -44
  7. data/lib/tic_tac_toe/game_factory.rb +51 -0
  8. data/lib/tic_tac_toe/player.rb +2 -2
  9. data/lib/tic_tac_toe/player_factory.rb +3 -3
  10. data/lib/tic_tac_toe/rules.rb +1 -1
  11. data/lib/tic_tac_toe/runner.rb +53 -0
  12. data/lib/tic_tac_toe/strategy/console_user.rb +1 -1
  13. data/lib/tic_tac_toe/strategy/minimax.rb +16 -18
  14. data/lib/tic_tac_toe/ui/console.rb +3 -3
  15. data/spec/integration/tictactoe/unbeatable_computer_spec.rb +3 -3
  16. data/spec/mocks/game.rb +1 -1
  17. data/spec/mocks/game_factory.rb +14 -0
  18. data/spec/mocks/player_factory.rb +2 -3
  19. data/spec/mocks/strategy/dynamic.rb +1 -1
  20. data/spec/tic_tac_toe/game_factory_spec.rb +78 -0
  21. data/spec/tic_tac_toe/game_spec.rb +78 -64
  22. data/spec/tic_tac_toe/player_factory_mock.rb +10 -0
  23. data/spec/tic_tac_toe/player_factory_spec.rb +9 -5
  24. data/spec/tic_tac_toe/player_spec.rb +16 -17
  25. data/spec/tic_tac_toe/runner_spec.rb +95 -0
  26. data/spec/tic_tac_toe/strategy/console_user_spec.rb +1 -1
  27. data/spec/tic_tac_toe/strategy/minimax_spec.rb +64 -65
  28. data/spec/tic_tac_toe/ui/console_spec.rb +1 -1
  29. data/tic_tac_toe_nhu.gemspec +1 -2
  30. metadata +8 -12
  31. data/lib/tic_tac_toe/game_state.rb +0 -35
  32. data/lib/tic_tac_toe/game_state_factory.rb +0 -56
  33. data/lib/tic_tac_toe/values.rb +0 -10
  34. data/spec/mocks/game_state.rb +0 -18
  35. data/spec/mocks/game_state_factory.rb +0 -14
  36. data/spec/mocks/player.rb +0 -16
  37. data/spec/tic_tac_toe/game_state_factory_spec.rb +0 -63
  38. data/spec/tic_tac_toe/game_state_spec.rb +0 -73
  39. data/spec/tic_tac_toe/values_spec.rb +0 -17
@@ -1,11 +1,10 @@
1
1
  require 'surrogate/rspec'
2
- require 'tic_tac_toe/values'
3
2
 
4
3
  class MockPlayerFactory
5
4
  Surrogate.endow(self)
6
5
 
7
- define(:human) {|name = "human", value = TicTacToe::VALUES[0]|}
8
- define(:computer) {|value = TicTacToe::VALUES[1]|}
6
+ define(:human) {|name = "Sue", value = "X"|}
7
+ define(:computer) {|board, value = "X", opponent="O"|}
9
8
  end
10
9
 
11
10
  describe TicTacToe::PlayerFactory do
@@ -9,7 +9,7 @@ class MockDynamicStrategy
9
9
  @moves << move
10
10
  end
11
11
 
12
- def move(*board)
12
+ def move
13
13
  @moves.shift
14
14
  end
15
15
 
@@ -0,0 +1,78 @@
1
+ require 'tic_tac_toe/spec_helper'
2
+ require 'tic_tac_toe/game_factory'
3
+ require 'tic_tac_toe/player_factory'
4
+ require 'mocks/player_factory'
5
+
6
+ describe TicTacToe::GameFactory do
7
+
8
+ before(:each) do
9
+ @board = "board"
10
+ @player_factory = MockPlayerFactory.new
11
+ @game_factory = TicTacToe::GameFactory.new(@player_factory)
12
+ end
13
+
14
+ it "ensures MockPlayerFactory has the same interface as PlayerFactory" do
15
+ MockPlayerFactory.should be_substitutable_for(TicTacToe::PlayerFactory)
16
+ end
17
+
18
+ it "returns 4 types of games" do
19
+ @game_factory.types.size.should == 4
20
+ end
21
+
22
+ it "sets the board in the game" do
23
+ game = @game_factory.create(1, @board)
24
+ game.board.should == @board
25
+ end
26
+
27
+ it "returns human vs computer game" do
28
+ human = "human"
29
+ computer = "computer"
30
+ @player_factory.will_have_human human
31
+ @player_factory.will_have_computer computer
32
+
33
+ game = @game_factory.create(1, @board)
34
+ game.current_player.should == human
35
+
36
+ @player_factory.was asked_for :computer
37
+ @player_factory.was asked_for :human
38
+ end
39
+
40
+ it "returns computer vs human game" do
41
+ human = "human"
42
+ computer = "computer"
43
+ @player_factory.will_have_human human
44
+ @player_factory.will_have_computer computer
45
+
46
+ game = @game_factory.create(2, @board)
47
+ game.current_player.should == computer
48
+
49
+ @player_factory.was asked_for :computer
50
+ @player_factory.was asked_for :human
51
+ end
52
+
53
+ it "returns user vs user game" do
54
+ human1 = "mary"
55
+ human2 = "alice"
56
+ @player_factory.will_have_human human1, human2
57
+
58
+ game = @game_factory.create(3, @board)
59
+ game.current_player.should == human1
60
+
61
+ @player_factory.was asked_for(:human).times(2)
62
+ end
63
+
64
+ it "returns computer vs computer game" do
65
+ computer1 = "computer1"
66
+ computer2 = "computer2"
67
+ @player_factory.will_have_computer computer2, computer1
68
+
69
+ game = @game_factory.create(4, @board)
70
+ game.current_player.should == computer2
71
+
72
+ @player_factory.was asked_for(:computer).times(2)
73
+ end
74
+
75
+ it "raises an error when the game type doesn't exist" do
76
+ lambda{@game_factory.create(5, @board)}.should raise_error(ArgumentError)
77
+ end
78
+ end
@@ -1,99 +1,113 @@
1
1
  require 'tic_tac_toe/spec_helper'
2
2
  require 'tic_tac_toe/game'
3
-
4
- require 'mocks/game_state_factory'
5
- require 'mocks/game_state'
6
- require 'mocks/ui/console'
7
- require 'mocks/player'
3
+ require 'tic_tac_toe/board'
4
+ require 'tic_tac_toe/player'
5
+ require 'mocks/strategy/dynamic'
8
6
 
9
7
  describe TicTacToe::Game do
10
- attr_reader :game, :ui, :game_state, :game_state_factory
11
-
12
8
  before(:each) do
13
- @game_state = MockGameState.factory
14
- @game_state_factory = MockGameStateFactory.factory create: game_state
15
- @ui = MockConsole.factory
16
- @game = TicTacToe::Game.new(@ui, @game_state_factory)
17
- end
9
+ @board = TicTacToe::Board.new
10
+
11
+ @player1_strategy = MockDynamicStrategy.new
12
+ @player1 = TicTacToe::Player.new("Todd", "X", @player1_strategy)
13
+
14
+ @player2_strategy = MockDynamicStrategy.new
15
+ @player2 = TicTacToe::Player.new("John", "O", @player2_strategy)
18
16
 
19
- it "displays a welcome message" do
20
- game.start
21
- ui.was told_to(:display_welcome_message)
17
+ @game = TicTacToe::Game.new(@board, @player1, @player2)
22
18
  end
23
19
 
24
- describe "create game state" do
25
- it "asks user for a game type" do
26
- game.start
27
- @ui.was asked_for(:game_type)
20
+ context "marking board" do
21
+ it "mark the board with user input when caller doesn't pass in a move" do
22
+ @player1_strategy.add_move(1)
23
+ @game.make_move
24
+ @board.unique_marked_values.should include(@player1.value)
28
25
  end
29
26
 
30
- it "asks game state factory to create a game with input game type" do
31
- game_type = 4
32
- ui.will_have_game_type 4
33
- game.start
34
- @game_state_factory.was told_to(:create).with(game_type)
27
+ it "does not mark the board if user doesn't return an input and caller didn't pass in a move" do
28
+ @player1_strategy.add_move(nil)
29
+ @game.make_move
30
+ @board.unique_marked_values.should_not include(@player1.value)
35
31
  end
36
32
 
37
- it "asks ui for game type again if the input is incorrect" do
38
- game_state_factory.will_create ArgumentError.new, game_state
39
- game.start
40
- ui.was asked_for(:game_type).times(2)
33
+ it "marks the board with the move passed in" do
34
+ @player1_strategy.add_move(1)
35
+ move = 2
36
+ @game.make_move(move)
37
+ @board.available_moves.should_not include(move)
41
38
  end
42
- end
43
-
44
- describe "play game" do
45
- attr_reader :player
46
39
 
47
- before(:each) do
48
- @player = MockPlayer.new
49
- game_state.will_game_over? false, true
50
- game_state.will_have_current_player @player
40
+ it "marks the board with player move when move passed in is nil" do
41
+ @player1_strategy.add_move(1)
42
+ @game.make_move(nil)
43
+ @board.available_moves.should_not include(1)
51
44
  end
52
45
 
53
- it "displays the board" do
54
- game.start
55
- ui.was told_to(:display_board)
46
+ it "marks the board with current player value when the move passed in" do
47
+ move = 2
48
+ @game.make_move(move)
49
+ @board.unique_marked_values.should include(@player1.value)
56
50
  end
51
+ end
57
52
 
58
- it "tells ui to display player turn" do
59
- game.start
60
- ui.was told_to(:display_player_turn).with(player)
53
+ describe "return winner player based on the value return from rules" do
54
+ it "is Todd when value is X" do
55
+ mark_board([0, 1, 2], @player1.value)
56
+ @game.winner.should == @player1
61
57
  end
62
58
 
63
- it "told player to move" do
64
- game.start
65
- player.was told_to(:move)
59
+ it "is John when it is O" do
60
+ mark_board([0, 1, 2], @player2.value)
61
+ @game.winner.should == @player2
66
62
  end
67
63
 
68
- it "tells player to move again if there is an error" do
69
- player.will_move TicTacToe::MoveNotAvailableError.new, nil
70
- game.start
71
- player.was told_to(:move).times(2)
64
+ it "is nil when no one wins" do
65
+ @game.winner.should be_nil
72
66
  end
67
+ end
73
68
 
74
- it "changes the player after a player move" do
75
- game.start
76
- game_state.was told_to(:change_player)
69
+ describe "changes player" do
70
+ it "doesn't change player if player 1 doesn't return a move" do
71
+ @game.current_player.should == @player1
72
+ @player1_strategy.add_move(nil)
73
+
74
+ @game.make_move
75
+ @game.current_player.should == @player1
77
76
  end
78
77
 
78
+ it "changes to player 2 after player 1 moves" do
79
+ @game.current_player.should == @player1
80
+ @player1_strategy.add_move(1)
81
+
82
+ @game.make_move
83
+ @game.current_player.should == @player2
84
+ end
79
85
  end
80
86
 
81
- describe "end game" do
82
- it "display a board at the end of the game" do
83
- game.start
84
- ui.was told_to(:display_board)
87
+ describe "game over" do
88
+ it "is over when there is a winner" do
89
+ mark_board([0, 1, 2], @player2.value)
90
+ @game.should be_over
91
+ end
92
+
93
+ it "is over when there is a tied" do
94
+ mark_board((0...9).to_a, "i")
95
+ @game.should be_over
96
+ end
97
+
98
+ it "is not over when there is no mark on the board" do
99
+ @game.should_not be_over
85
100
  end
86
101
 
87
- it "asks ui to display a winner if there is a winner" do
88
- winner = "Winner"
89
- game_state.will_have_winner winner
90
- game.start
91
- ui.was told_to(:display_winner).with(winner)
102
+ it "is not over when there is no winner or a tied" do
103
+ mark_board([1, 2], @player1.value)
104
+ @game.should_not be_over
92
105
  end
106
+ end
93
107
 
94
- it "asks ui to display a draw" do
95
- game.start
96
- ui.was told_to(:display_tied_game)
108
+ def mark_board(moves, value)
109
+ moves.each do |m|
110
+ @board.mark(m, value)
97
111
  end
98
112
  end
99
113
  end
@@ -0,0 +1,10 @@
1
+ class PlayerFactoryMock
2
+
3
+ def human(name = "User", value = "X")
4
+ "Human"
5
+ end
6
+
7
+ def computer(board, value = "O", opponent_value = "X")
8
+ "Computer"
9
+ end
10
+ end
@@ -2,7 +2,6 @@ require 'tic_tac_toe/spec_helper'
2
2
  require 'tic_tac_toe/player_factory'
3
3
  require 'tic_tac_toe/strategy/minimax'
4
4
  require 'tic_tac_toe/strategy/console_user'
5
- require 'tic_tac_toe/values'
6
5
 
7
6
  describe TicTacToe::PlayerFactory do
8
7
 
@@ -33,22 +32,27 @@ describe TicTacToe::PlayerFactory do
33
32
  end
34
33
 
35
34
  context "computer player" do
35
+ before(:each) do
36
+ @board = "fake board"
37
+ end
38
+
36
39
  it "returns a computer player with given value" do
37
40
  computer_value = "Danny"
38
- player = @factory.computer(computer_value)
41
+ opponent_value = "Bill"
42
+ player = @factory.computer(@board, computer_value, opponent_value)
39
43
  player.value.should == computer_value
40
44
  end
41
45
 
42
46
  it "checks default strategy" do
43
- @factory.computer.strategy.should be_kind_of(TicTacToe::Strategy::Minimax)
47
+ @factory.computer(@board).strategy.should be_kind_of(TicTacToe::Strategy::Minimax)
44
48
  end
45
49
 
46
50
  it "checks default name" do
47
- @factory.computer.name.should == "Computer"
51
+ @factory.computer(@board).name.should == "Computer"
48
52
  end
49
53
 
50
54
  it "checks default value" do
51
- @factory.computer.value.should == "O"
55
+ @factory.computer(@board).value.should == "O"
52
56
  end
53
57
  end
54
58
 
@@ -1,33 +1,32 @@
1
1
  require 'tic_tac_toe/spec_helper'
2
2
  require 'tic_tac_toe/player'
3
- require 'tic_tac_toe/board'
4
- require 'tic_tac_toe/values'
5
3
  require 'mocks/strategy/dynamic'
6
4
 
7
5
  describe TicTacToe::Player do
8
- before(:each) do
9
- @move = 4
10
- @value = TicTacToe::VALUES[0]
11
- @name = "blu"
12
- @strategy = MockDynamicStrategy.new([@move])
13
- @player = TicTacToe::Player.new(@name, @value, @strategy)
14
- end
15
6
 
16
7
  it "gets name" do
17
- @player.name.should == @name
8
+ name = "bruce"
9
+ player = TicTacToe::Player.new(name, nil, nil)
10
+ player.name.should == name
18
11
  end
19
12
 
20
13
  it "gets player value" do
21
- @player.value.should == @value
14
+ value = "X"
15
+ player = TicTacToe::Player.new(nil, value, nil)
16
+ player.value.should == value
22
17
  end
23
18
 
24
- it "gets strategy" do
25
- @player.strategy.should == @strategy
19
+ it "gets player's move" do
20
+ move = 4
21
+ strategy = MockDynamicStrategy.new([4])
22
+ player = TicTacToe::Player.new(nil, nil, strategy)
23
+ player.move.should == move
26
24
  end
27
25
 
28
- it "makes move" do
29
- board = TicTacToe::Board.new
30
- @player.move(board)
31
- board.available_moves.should_not include(@move)
26
+ it "gets strategy" do
27
+ strategy = MockDynamicStrategy.new([4])
28
+ player = TicTacToe::Player.new(nil, nil, strategy)
29
+ player.strategy.should == strategy
30
+
32
31
  end
33
32
  end
@@ -0,0 +1,95 @@
1
+ require 'tic_tac_toe/spec_helper'
2
+ require 'tic_tac_toe/runner'
3
+ require 'tic_tac_toe/player'
4
+ require 'tic_tac_toe/game'
5
+ require 'tic_tac_toe/rules'
6
+ require 'tic_tac_toe/board'
7
+ require 'mocks/game'
8
+ require 'mocks/game_factory'
9
+ require 'mocks/ui/console'
10
+ require 'mocks/strategy/dynamic'
11
+ require 'mocks/rules'
12
+
13
+ describe TicTacToe::Runner do
14
+ before(:each) do
15
+ @ui = MockConsole.factory
16
+ @todd = TicTacToe::Player.new("Todd", "X", MockDynamicStrategy.new([1,2,3]))
17
+ @game = MockGame.factory current_player: @todd, winner: @todd
18
+ @game_factory = MockGameFactory.factory create: @game
19
+ @controller = TicTacToe::Runner.new(@ui, @game_factory)
20
+ end
21
+
22
+ describe "starts game" do
23
+ it "displays welcome message" do
24
+ @controller.start
25
+ @ui.was told_to(:display_welcome_message)
26
+ end
27
+
28
+ it "asked ui to get game type" do
29
+ @controller.start
30
+ @ui.was asked_for(:game_type)
31
+ end
32
+
33
+ it "creates a game based on user input" do
34
+ @controller.start
35
+ @game_factory.was told_to(:create)
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
42
+ end
43
+
44
+ describe "play game" do
45
+ before(:each) do
46
+ @game.will_over? false, true
47
+ end
48
+
49
+ it "display board" do
50
+ @controller.start
51
+ @ui.was told_to(:display_board)
52
+ end
53
+
54
+ it "displays whose turn it is" do
55
+ @controller.start
56
+ @ui.was told_to(:display_player_turn).with(@todd)
57
+ end
58
+
59
+ it "tells game to make a move" do
60
+ @game.will_over? false, true
61
+ @controller.start
62
+ @game.was told_to(:make_move)
63
+ end
64
+
65
+ it "asks for game move until game is over" do
66
+ @game.will_over? false, false, false, true
67
+ @controller.start
68
+ @game.was told_to(:make_move).times(3)
69
+ end
70
+
71
+ it "displays message when square is not available" do
72
+ @game.will_make_move TicTacToe::MoveNotAvailableError.new
73
+ @controller.start
74
+ @ui.was told_to(:display_square_not_available)
75
+ end
76
+ end
77
+
78
+ describe "end game" do
79
+ it "displays the board when the game is over" do
80
+ @controller.start
81
+ @ui.was told_to(:display_board)
82
+ end
83
+
84
+ it "notifies user when player wins" do
85
+ @controller.start
86
+ @ui.was told_to(:display_winner).with(@todd)
87
+ end
88
+
89
+ it "notifies user when it's a tied game" do
90
+ @game.will_have_winner nil
91
+ @controller.start
92
+ @ui.was told_to(:display_tied_game)
93
+ end
94
+ end
95
+ end
@@ -13,7 +13,7 @@ describe TicTacToe::Strategy::ConsoleUser do
13
13
  it "prompts the user for a move" do
14
14
  @output.should_receive(:puts).with("Please enter a square number that is not marked: ")
15
15
  @input.should_receive(:gets).and_return("3")
16
- @strategy.move(@board)
16
+ @strategy.move
17
17
  end
18
18
 
19
19
  it "returns a number when user enters a number" do