tic_tac_toe_nhu 0.0.11 → 0.1.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.
- checksums.yaml +4 -4
- data/bin/tic_tac_toe +2 -2
- data/coverage/.resultset.json +52 -65
- data/lib/tic_tac_toe/board.rb +1 -1
- data/lib/tic_tac_toe/game.rb +21 -19
- data/lib/tic_tac_toe/game_factory.rb +11 -33
- data/lib/tic_tac_toe/player.rb +2 -2
- data/lib/tic_tac_toe/player_factory.rb +19 -4
- data/lib/tic_tac_toe/rules.rb +1 -1
- data/lib/tic_tac_toe/runner.rb +27 -20
- data/lib/tic_tac_toe/strategy/console_user.rb +1 -1
- data/lib/tic_tac_toe/strategy/minimax.rb +18 -16
- data/lib/tic_tac_toe/ui/console.rb +2 -2
- data/lib/tic_tac_toe/values.rb +10 -0
- data/spec/{integration → acceptance}/tictactoe/unbeatable_computer_spec.rb +8 -6
- data/spec/mocks/game.rb +2 -2
- data/spec/mocks/game_factory.rb +1 -1
- data/spec/mocks/player.rb +16 -0
- data/spec/mocks/player_factory.rb +3 -2
- data/spec/mocks/strategy/dynamic.rb +1 -1
- data/spec/tic_tac_toe/game_factory_spec.rb +31 -50
- data/spec/tic_tac_toe/game_spec.rb +53 -62
- data/spec/tic_tac_toe/player_factory_spec.rb +21 -28
- data/spec/tic_tac_toe/player_spec.rb +12 -17
- data/spec/tic_tac_toe/runner_spec.rb +49 -56
- data/spec/tic_tac_toe/strategy/console_user_spec.rb +1 -1
- data/spec/tic_tac_toe/strategy/minimax_spec.rb +65 -64
- data/spec/tic_tac_toe/ui/console_spec.rb +2 -2
- data/spec/tic_tac_toe/values_spec.rb +17 -0
- data/tic_tac_toe_nhu.gemspec +2 -1
- metadata +7 -4
- data/spec/tic_tac_toe/player_factory_mock.rb +0 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 76f4600254a71f4f37fe5efa7f74a8000b5d7b35
|
4
|
+
data.tar.gz: 81f2f459fa5e1a867e053d42f5dfdfe2ae4dc27f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5eae5eeee50f815eaac5fb338c1aba07e9d54ad669cd179f6a333ef4b693aa333145b12825f61696eab943103b1934f4ca101e10f7bff4c10f9e702bc54a3912
|
7
|
+
data.tar.gz: b9e661172ad637011bd6b36e7a0ce4cb5a56bf17f114277b9e1da7ad57bc4d03f29269e6c7328d8fd8d147b44fc39b3b7feae7d9bd8cbe7004ee8f8a4665ca98
|
data/bin/tic_tac_toe
CHANGED
data/coverage/.resultset.json
CHANGED
@@ -5,56 +5,35 @@
|
|
5
5
|
1,
|
6
6
|
1,
|
7
7
|
1,
|
8
|
-
null,
|
9
|
-
1,
|
10
|
-
1,
|
11
|
-
1,
|
12
|
-
13,
|
13
|
-
null,
|
14
|
-
null,
|
15
|
-
1,
|
16
|
-
6,
|
17
|
-
null,
|
18
|
-
null,
|
19
|
-
1,
|
20
|
-
6,
|
21
|
-
null,
|
22
|
-
2,
|
23
|
-
null,
|
24
|
-
1,
|
25
|
-
null,
|
26
|
-
1,
|
27
|
-
null,
|
28
|
-
1,
|
29
|
-
null,
|
30
8
|
1,
|
31
9
|
null,
|
32
|
-
null,
|
33
|
-
null,
|
34
10
|
1,
|
35
11
|
1,
|
36
12
|
1,
|
13
|
+
11,
|
37
14
|
null,
|
38
15
|
null,
|
39
16
|
1,
|
40
|
-
|
17
|
+
11,
|
18
|
+
11,
|
41
19
|
null,
|
42
20
|
null,
|
43
21
|
1,
|
44
|
-
|
22
|
+
5,
|
45
23
|
null,
|
24
|
+
5,
|
25
|
+
4,
|
26
|
+
4,
|
27
|
+
4,
|
46
28
|
null,
|
47
29
|
1,
|
48
|
-
1,
|
49
30
|
null,
|
50
31
|
null,
|
51
|
-
1,
|
52
|
-
5,
|
53
|
-
null,
|
54
32
|
null,
|
55
33
|
null
|
56
34
|
],
|
57
35
|
"/Users/nhunguyen/Documents/Ruby/tictactoe/lib/tic_tac_toe/game.rb": [
|
36
|
+
1,
|
58
37
|
1,
|
59
38
|
null,
|
60
39
|
1,
|
@@ -62,26 +41,25 @@
|
|
62
41
|
1,
|
63
42
|
null,
|
64
43
|
1,
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
19,
|
44
|
+
17,
|
45
|
+
17,
|
46
|
+
17,
|
69
47
|
null,
|
70
48
|
null,
|
71
49
|
1,
|
72
|
-
|
73
|
-
7,
|
74
|
-
5,
|
75
|
-
5,
|
76
|
-
null,
|
50
|
+
2,
|
77
51
|
null,
|
78
52
|
null,
|
79
53
|
1,
|
80
|
-
|
54
|
+
3,
|
81
55
|
null,
|
82
56
|
null,
|
83
57
|
1,
|
84
|
-
|
58
|
+
11,
|
59
|
+
11,
|
60
|
+
9,
|
61
|
+
9,
|
62
|
+
null,
|
85
63
|
null,
|
86
64
|
null,
|
87
65
|
1,
|
@@ -90,9 +68,11 @@
|
|
90
68
|
null,
|
91
69
|
null,
|
92
70
|
1,
|
93
|
-
|
94
|
-
|
71
|
+
8,
|
72
|
+
null,
|
95
73
|
null,
|
74
|
+
1,
|
75
|
+
9,
|
96
76
|
null,
|
97
77
|
null,
|
98
78
|
null
|
@@ -104,52 +84,59 @@
|
|
104
84
|
null,
|
105
85
|
1,
|
106
86
|
1,
|
87
|
+
null,
|
107
88
|
1,
|
108
|
-
|
109
|
-
|
110
|
-
12,
|
111
|
-
12,
|
89
|
+
10,
|
90
|
+
10,
|
112
91
|
null,
|
113
92
|
null,
|
114
93
|
1,
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
94
|
+
10,
|
95
|
+
10,
|
96
|
+
10,
|
97
|
+
10,
|
98
|
+
10,
|
120
99
|
null,
|
121
100
|
null,
|
122
101
|
1,
|
123
102
|
1,
|
124
|
-
|
125
|
-
13,
|
126
|
-
13,
|
103
|
+
null,
|
127
104
|
1,
|
105
|
+
11,
|
106
|
+
11,
|
107
|
+
11,
|
128
108
|
1,
|
109
|
+
1,
|
110
|
+
null,
|
129
111
|
null,
|
130
112
|
null,
|
113
|
+
1,
|
114
|
+
3,
|
115
|
+
3,
|
116
|
+
3,
|
117
|
+
null,
|
131
118
|
null,
|
132
119
|
1,
|
133
|
-
|
134
|
-
|
135
|
-
7,
|
136
|
-
7,
|
137
|
-
7,
|
120
|
+
4,
|
121
|
+
4,
|
138
122
|
1,
|
139
123
|
1,
|
140
124
|
null,
|
141
125
|
null,
|
142
126
|
null,
|
143
127
|
1,
|
144
|
-
|
145
|
-
|
146
|
-
11,
|
147
|
-
null,
|
128
|
+
10,
|
129
|
+
10,
|
148
130
|
1,
|
149
131
|
null,
|
132
|
+
9,
|
150
133
|
null,
|
151
134
|
null,
|
152
135
|
null,
|
136
|
+
1,
|
137
|
+
13,
|
138
|
+
null,
|
139
|
+
null,
|
153
140
|
null
|
154
141
|
],
|
155
142
|
"/Users/nhunguyen/Documents/Ruby/tictactoe/lib/tic_tac_toe/ui/console.rb": [
|
@@ -228,6 +215,6 @@
|
|
228
215
|
null
|
229
216
|
]
|
230
217
|
},
|
231
|
-
"timestamp":
|
218
|
+
"timestamp": 1376342502
|
232
219
|
}
|
233
220
|
}
|
data/lib/tic_tac_toe/board.rb
CHANGED
data/lib/tic_tac_toe/game.rb
CHANGED
@@ -1,41 +1,43 @@
|
|
1
|
+
require 'tic_tac_toe/board'
|
1
2
|
require 'tic_tac_toe/rules'
|
2
3
|
|
3
4
|
module TicTacToe
|
4
5
|
class Game
|
5
|
-
attr_reader :
|
6
|
+
attr_reader :board, :current_player
|
6
7
|
|
7
|
-
def initialize(
|
8
|
+
def initialize(players, board = TicTacToe::Board.new)
|
8
9
|
@board = board
|
9
|
-
@
|
10
|
-
@
|
11
|
-
@rules = TicTacToe::Rules.new(@board)
|
10
|
+
@players = players
|
11
|
+
@current_player = players[0]
|
12
12
|
end
|
13
13
|
|
14
|
-
def
|
15
|
-
|
14
|
+
def game_over?
|
15
|
+
rules.game_over?
|
16
|
+
end
|
17
|
+
|
18
|
+
def winner
|
19
|
+
player(rules.winner)
|
20
|
+
end
|
21
|
+
|
22
|
+
def make_player_move(*move)
|
23
|
+
player_move = move[0] || @current_player.move(board)
|
16
24
|
if player_move
|
17
25
|
@board.mark(player_move, @current_player.value)
|
18
26
|
change_player
|
19
27
|
end
|
20
28
|
end
|
21
29
|
|
22
|
-
|
23
|
-
|
30
|
+
private
|
31
|
+
def rules
|
32
|
+
@rules ||= TicTacToe::Rules.new(board)
|
24
33
|
end
|
25
34
|
|
26
|
-
def
|
27
|
-
|
35
|
+
def player(value)
|
36
|
+
@players.detect {|p| p.value == value}
|
28
37
|
end
|
29
38
|
|
30
|
-
private
|
31
39
|
def change_player
|
32
|
-
@current_player = (@
|
40
|
+
@current_player = (@players[0] == @current_player)? @players[1] : @players[0]
|
33
41
|
end
|
34
|
-
|
35
|
-
def player(mark)
|
36
|
-
return @player1 if mark == @player1.value
|
37
|
-
return @player2 if mark == @player2.value
|
38
|
-
end
|
39
|
-
|
40
42
|
end
|
41
43
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'tic_tac_toe/game'
|
2
2
|
require 'tic_tac_toe/board'
|
3
3
|
require 'tic_tac_toe/player_factory'
|
4
|
+
require 'tic_tac_toe/values'
|
4
5
|
|
5
6
|
module TicTacToe
|
6
7
|
class GameFactory
|
@@ -9,43 +10,20 @@ module TicTacToe
|
|
9
10
|
end
|
10
11
|
|
11
12
|
def types
|
12
|
-
|
13
|
+
player_types = @player_factory.types
|
14
|
+
player_types.product player_types
|
13
15
|
end
|
14
16
|
|
15
|
-
def create(
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
human_human_game(board)
|
23
|
-
when 4
|
24
|
-
computer_computer_game(board)
|
17
|
+
def create(game_type)
|
18
|
+
player_types = types[game_type-1]
|
19
|
+
|
20
|
+
if player_types
|
21
|
+
player1 = @player_factory.create(player_types[0], TicTacToe::VALUES[0])
|
22
|
+
player2 = @player_factory.create(player_types[1], TicTacToe::VALUES[1])
|
23
|
+
TicTacToe::Game.new([player1, player2])
|
25
24
|
else
|
26
|
-
raise ArgumentError, "Type does not exist. Please select a number corresponding to the game type."
|
25
|
+
raise ArgumentError, "Type #{game_type} does not exist. Please select a number corresponding to the game type."
|
27
26
|
end
|
28
27
|
end
|
29
|
-
|
30
|
-
private
|
31
|
-
def computer_human_game(board)
|
32
|
-
create_game(board, @player_factory.computer(board), @player_factory.human)
|
33
|
-
end
|
34
|
-
|
35
|
-
def human_computer_game(board)
|
36
|
-
create_game(board, @player_factory.human, @player_factory.computer(board))
|
37
|
-
end
|
38
|
-
|
39
|
-
def human_human_game(board)
|
40
|
-
create_game(board, @player_factory.human, @player_factory.human("Friend", "O"))
|
41
|
-
end
|
42
|
-
|
43
|
-
def computer_computer_game(board)
|
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)
|
49
|
-
end
|
50
28
|
end
|
51
29
|
end
|
data/lib/tic_tac_toe/player.rb
CHANGED
@@ -1,16 +1,31 @@
|
|
1
1
|
require 'tic_tac_toe/strategy/minimax'
|
2
2
|
require 'tic_tac_toe/strategy/console_user'
|
3
3
|
require 'tic_tac_toe/player'
|
4
|
+
require 'tic_tac_toe/values'
|
4
5
|
|
5
6
|
module TicTacToe
|
6
7
|
class PlayerFactory
|
7
8
|
|
8
|
-
def
|
9
|
-
|
9
|
+
def types
|
10
|
+
[:human, :computer]
|
10
11
|
end
|
11
12
|
|
12
|
-
def
|
13
|
-
|
13
|
+
def create(player_type, value)
|
14
|
+
case player_type
|
15
|
+
when :human
|
16
|
+
human(value)
|
17
|
+
when :computer
|
18
|
+
computer(value)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
def human(value)
|
24
|
+
TicTacToe::Player.new("User", value, TicTacToe::Strategy::ConsoleUser.new)
|
25
|
+
end
|
26
|
+
|
27
|
+
def computer(value)
|
28
|
+
ai = TicTacToe::Strategy::Minimax.new(value)
|
14
29
|
TicTacToe::Player.new("Computer", value, ai)
|
15
30
|
end
|
16
31
|
end
|
data/lib/tic_tac_toe/rules.rb
CHANGED
data/lib/tic_tac_toe/runner.rb
CHANGED
@@ -4,50 +4,57 @@ require 'tic_tac_toe/board'
|
|
4
4
|
|
5
5
|
module TicTacToe
|
6
6
|
class Runner
|
7
|
-
|
8
|
-
def initialize(ui = TicTacToe::Console.new,
|
7
|
+
|
8
|
+
def initialize(ui = TicTacToe::Console.new, game_state_factory = TicTacToe::GameFactory.new)
|
9
9
|
@ui = ui
|
10
|
-
@
|
11
|
-
@game_factory = game_factory
|
10
|
+
@game_state_factory = game_state_factory
|
12
11
|
end
|
13
12
|
|
14
13
|
def start
|
15
|
-
|
16
|
-
@
|
17
|
-
play until
|
18
|
-
|
14
|
+
ui.display_welcome_message
|
15
|
+
@game_state = create_game_state
|
16
|
+
play until game_state.game_over?
|
17
|
+
ui.display_board(board)
|
19
18
|
display_result
|
20
19
|
end
|
21
20
|
|
22
21
|
private
|
23
|
-
|
24
|
-
|
22
|
+
attr_reader :ui, :game_state, :game_state_factory
|
23
|
+
|
24
|
+
def create_game_state
|
25
|
+
game_type = ui.game_type
|
25
26
|
begin
|
26
|
-
|
27
|
+
game_state_factory.create(game_type)
|
27
28
|
rescue ArgumentError
|
28
|
-
|
29
|
+
create_game_state
|
29
30
|
end
|
30
31
|
end
|
31
32
|
|
32
33
|
def play
|
33
|
-
|
34
|
-
|
35
|
-
|
34
|
+
ui.display_board(board)
|
35
|
+
ui.display_player_turn(game_state.current_player)
|
36
|
+
make_player_move
|
37
|
+
end
|
38
|
+
|
39
|
+
def make_player_move
|
36
40
|
begin
|
37
|
-
|
41
|
+
game_state.make_player_move
|
38
42
|
rescue MoveNotAvailableError
|
39
|
-
|
43
|
+
make_player_move
|
40
44
|
end
|
41
45
|
end
|
42
46
|
|
43
47
|
def display_result
|
44
|
-
winner =
|
48
|
+
winner = game_state.winner
|
45
49
|
if winner
|
46
|
-
|
50
|
+
ui.display_winner(winner)
|
47
51
|
else
|
48
|
-
|
52
|
+
ui.display_tied_game
|
49
53
|
end
|
50
54
|
end
|
51
55
|
|
56
|
+
def board
|
57
|
+
game_state.board
|
58
|
+
end
|
52
59
|
end
|
53
60
|
end
|