tactical_tic_tac_toe 0.2.0 → 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.
- checksums.yaml +4 -4
- data/lib/board.rb +34 -23
- data/lib/command_line_interface.rb +1 -2
- data/lib/computer_player.rb +4 -4
- data/lib/game.rb +3 -3
- data/lib/player_factory.rb +11 -11
- data/spec/board_spec.rb +59 -61
- data/spec/command_line_interface_spec.rb +24 -19
- data/spec/computer_player_spec.rb +25 -25
- data/spec/game_spec.rb +7 -7
- data/spec/human_player_spec.rb +1 -2
- data/spec/player_factory_spec.rb +9 -9
- data/spec/spec_helper.rb +3 -32
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a48e3069e89982be0b1927358042ccdf5931e344
|
|
4
|
+
data.tar.gz: 199d9b74f5bc4c0eab7e68ab78a6ee8534832688
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 87fa250b8b7f466e6fb30c39f4db48a08aa6e7bc79494180d63b5698a67ce89d1418f4bcda55b1c45dd6b8b543b92c33d8b7999c6aa5f4ba16b5e5da6af3470c
|
|
7
|
+
data.tar.gz: 1928f444469351637902c7a8afaecd00fed4fa18b5ad883ba913b730a1957446000b91bed94194f44ae96659fbf08402c2c897af6e34786081305a5c0ea737cd
|
data/lib/board.rb
CHANGED
|
@@ -5,19 +5,25 @@ module TicTacToe
|
|
|
5
5
|
attr_reader :size, :last_move_made
|
|
6
6
|
|
|
7
7
|
def initialize(parameters)
|
|
8
|
-
@size = parameters[:size]
|
|
9
|
-
@
|
|
8
|
+
@size = parameters[:size] || infer_size(parameters[:marked_spaces])
|
|
9
|
+
@spaces = parameters[:marked_spaces] || blank_spaces
|
|
10
10
|
@last_move_made = parameters[:last_move_made]
|
|
11
11
|
end
|
|
12
12
|
|
|
13
|
-
def
|
|
14
|
-
@
|
|
13
|
+
def read_space(coordinates)
|
|
14
|
+
@spaces[coordinates_to_flat_index(coordinates)]
|
|
15
15
|
end
|
|
16
16
|
|
|
17
|
-
def
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
def mark_space(mark, coordinates)
|
|
18
|
+
marked_spaces = @spaces.dup
|
|
19
|
+
marked_spaces[coordinates_to_flat_index(coordinates)] = mark
|
|
20
|
+
|
|
21
|
+
Board.new(marked_spaces: marked_spaces, last_move_made: coordinates)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def last_mark_made
|
|
25
|
+
return if @last_move_made.nil?
|
|
26
|
+
self.read_space(last_move_made)
|
|
21
27
|
end
|
|
22
28
|
|
|
23
29
|
def lines
|
|
@@ -30,27 +36,22 @@ module TicTacToe
|
|
|
30
36
|
(0...@size).to_a.repeated_permutation(2).to_a
|
|
31
37
|
end
|
|
32
38
|
|
|
33
|
-
def
|
|
39
|
+
def blank_space_coordinates
|
|
34
40
|
all_coordinates.reject { |coordinates| marked?(coordinates) }
|
|
35
41
|
end
|
|
36
42
|
|
|
37
|
-
def
|
|
38
|
-
|
|
39
|
-
self.read_cell(*last_move_made)
|
|
43
|
+
def out_of_bounds?(coordinates)
|
|
44
|
+
coordinates.any? { |i| !i.between?(0, @size - 1) }
|
|
40
45
|
end
|
|
41
46
|
|
|
42
47
|
def blank?(coordinates)
|
|
43
|
-
self.
|
|
48
|
+
self.read_space(coordinates) == BLANK_MARK
|
|
44
49
|
end
|
|
45
50
|
|
|
46
51
|
def marked?(coordinates)
|
|
47
52
|
!blank?(coordinates)
|
|
48
53
|
end
|
|
49
54
|
|
|
50
|
-
def out_of_bounds?(coordinates)
|
|
51
|
-
coordinates.any? { |i| !i.between?(0, @size - 1) }
|
|
52
|
-
end
|
|
53
|
-
|
|
54
55
|
def all_blank?
|
|
55
56
|
all_coordinates.all? { |coordinates| blank?(coordinates) }
|
|
56
57
|
end
|
|
@@ -61,31 +62,41 @@ module TicTacToe
|
|
|
61
62
|
|
|
62
63
|
def has_winning_line?
|
|
63
64
|
lines.each do |line|
|
|
64
|
-
return true if line.first != BLANK_MARK && line.all? { |
|
|
65
|
+
return true if line.first != BLANK_MARK && line.all? { |mark| mark == line.first }
|
|
65
66
|
end
|
|
66
67
|
false
|
|
67
68
|
end
|
|
68
69
|
|
|
69
70
|
private
|
|
70
71
|
|
|
71
|
-
def
|
|
72
|
+
def infer_size(marked_spaces)
|
|
73
|
+
return if marked_spaces.nil?
|
|
74
|
+
Math.sqrt(marked_spaces.count).to_i
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def coordinates_to_flat_index(coordinates)
|
|
78
|
+
row, col = coordinates
|
|
79
|
+
row * @size + col
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def blank_spaces
|
|
72
83
|
Array.new(@size**2) { BLANK_MARK }
|
|
73
84
|
end
|
|
74
85
|
|
|
75
86
|
def row_at(row)
|
|
76
|
-
(0...@size).map { |col| self.
|
|
87
|
+
(0...@size).map { |col| self.read_space([row, col]) }
|
|
77
88
|
end
|
|
78
89
|
|
|
79
90
|
def col_at(col)
|
|
80
|
-
(0...@size).map { |row| self.
|
|
91
|
+
(0...@size).map { |row| self.read_space([row, col]) }
|
|
81
92
|
end
|
|
82
93
|
|
|
83
94
|
def left_diag
|
|
84
|
-
(0...@size).map { |index| self.
|
|
95
|
+
(0...@size).map { |index| self.read_space([index, index]) }
|
|
85
96
|
end
|
|
86
97
|
|
|
87
98
|
def right_diag
|
|
88
|
-
(0...@size).map { |row| self.
|
|
99
|
+
(0...@size).map { |row| self.read_space([row, @size - row - 1]) }
|
|
89
100
|
end
|
|
90
101
|
end
|
|
91
102
|
end
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
module TicTacToe
|
|
2
2
|
class CommandLineInterface
|
|
3
|
-
|
|
4
3
|
def initialize(parameters)
|
|
5
4
|
@input = parameters[:input]
|
|
6
5
|
@output = parameters[:output]
|
|
@@ -86,7 +85,7 @@ EOS
|
|
|
86
85
|
(0...board.size).each do |row|
|
|
87
86
|
output_string += col_separator
|
|
88
87
|
(0...board.size).each do |col|
|
|
89
|
-
output_string += " #{board.
|
|
88
|
+
output_string += " #{board.read_space([row, col]) || " "} " + col_separator
|
|
90
89
|
end
|
|
91
90
|
output_string += "\n" + row_separator
|
|
92
91
|
end
|
data/lib/computer_player.rb
CHANGED
|
@@ -47,9 +47,9 @@ module TicTacToe
|
|
|
47
47
|
board = node.fetch(:board)
|
|
48
48
|
current_player_mark = node.fetch(:current_player_mark)
|
|
49
49
|
|
|
50
|
-
board.
|
|
50
|
+
board.blank_space_coordinates.map do |coordinates|
|
|
51
51
|
child_node = {
|
|
52
|
-
board: board.
|
|
52
|
+
board: board.mark_space(current_player_mark, coordinates),
|
|
53
53
|
current_player_mark: toggle_mark(current_player_mark),
|
|
54
54
|
last_move_made: coordinates
|
|
55
55
|
}
|
|
@@ -71,8 +71,8 @@ module TicTacToe
|
|
|
71
71
|
board = node.fetch(:board)
|
|
72
72
|
|
|
73
73
|
board.lines.each do |line|
|
|
74
|
-
return 1 if line.all? { |
|
|
75
|
-
return -1 if line.all? { |
|
|
74
|
+
return 1 if line.all? { |mark| mark == @player_mark }
|
|
75
|
+
return -1 if line.all? { |mark| mark == @opponent_mark }
|
|
76
76
|
end
|
|
77
77
|
0
|
|
78
78
|
end
|
data/lib/game.rb
CHANGED
|
@@ -37,7 +37,7 @@ module TicTacToe
|
|
|
37
37
|
def handle_one_turn(current_player)
|
|
38
38
|
@interface.show_game_board(@board)
|
|
39
39
|
coordinates = get_valid_move(current_player)
|
|
40
|
-
@board = @board.
|
|
40
|
+
@board = @board.mark_space(current_player.player_mark, coordinates)
|
|
41
41
|
@interface.report_move(current_player.player_mark, coordinates)
|
|
42
42
|
end
|
|
43
43
|
|
|
@@ -77,12 +77,12 @@ module TicTacToe
|
|
|
77
77
|
end
|
|
78
78
|
|
|
79
79
|
def create_player(mark, type)
|
|
80
|
-
|
|
80
|
+
player_parameters = {
|
|
81
81
|
type: type,
|
|
82
82
|
game: self,
|
|
83
83
|
player_mark: mark
|
|
84
84
|
}
|
|
85
|
-
PlayerFactory.build(
|
|
85
|
+
PlayerFactory.build(player_parameters)
|
|
86
86
|
end
|
|
87
87
|
end
|
|
88
88
|
end
|
data/lib/player_factory.rb
CHANGED
|
@@ -4,30 +4,30 @@ require "available_player_types"
|
|
|
4
4
|
|
|
5
5
|
module TicTacToe
|
|
6
6
|
module PlayerFactory
|
|
7
|
-
def self.build(
|
|
8
|
-
case
|
|
7
|
+
def self.build(parameters)
|
|
8
|
+
case parameters[:type]
|
|
9
9
|
when AvailablePlayerTypes::HUMAN
|
|
10
|
-
create_human_player(
|
|
10
|
+
create_human_player(parameters)
|
|
11
11
|
when AvailablePlayerTypes::COMPUTER
|
|
12
|
-
create_computer_player(
|
|
12
|
+
create_computer_player(parameters)
|
|
13
13
|
end
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
private
|
|
17
17
|
|
|
18
|
-
def self.create_human_player(
|
|
18
|
+
def self.create_human_player(parameters)
|
|
19
19
|
human_parameters = {
|
|
20
|
-
player_mark:
|
|
21
|
-
interface:
|
|
20
|
+
player_mark: parameters[:player_mark],
|
|
21
|
+
interface: parameters[:game].interface
|
|
22
22
|
}
|
|
23
23
|
HumanPlayer.new(human_parameters)
|
|
24
24
|
end
|
|
25
25
|
|
|
26
|
-
def self.create_computer_player(
|
|
26
|
+
def self.create_computer_player(parameters)
|
|
27
27
|
computer_parameters = {
|
|
28
|
-
player_mark:
|
|
29
|
-
opponent_mark: (
|
|
30
|
-
board:
|
|
28
|
+
player_mark: parameters[:player_mark],
|
|
29
|
+
opponent_mark: (parameters[:game].player_marks - [parameters[:player_mark]]).pop,
|
|
30
|
+
board: parameters[:game].board
|
|
31
31
|
}
|
|
32
32
|
ComputerPlayer.new(computer_parameters)
|
|
33
33
|
end
|
data/spec/board_spec.rb
CHANGED
|
@@ -11,26 +11,26 @@ module TicTacToe
|
|
|
11
11
|
let(:o) { @default_player_marks.last }
|
|
12
12
|
|
|
13
13
|
describe "#initialize" do
|
|
14
|
-
context "given
|
|
15
|
-
let(:
|
|
14
|
+
context "given a set of preexisting marks" do
|
|
15
|
+
let(:marked_spaces) do
|
|
16
16
|
[ x, _, _,
|
|
17
17
|
_, o, _,
|
|
18
18
|
_, _, x ]
|
|
19
19
|
end
|
|
20
20
|
|
|
21
|
-
it "generates a board with the specified marks in each
|
|
22
|
-
board =
|
|
21
|
+
it "generates a board with the specified marks in each space" do
|
|
22
|
+
board = build_board(marked_spaces)
|
|
23
23
|
|
|
24
|
-
board.all_coordinates.zip(
|
|
25
|
-
expect(board.
|
|
24
|
+
board.all_coordinates.zip(marked_spaces).each do |coordinates, mark|
|
|
25
|
+
expect(board.read_space(coordinates)).to eq mark
|
|
26
26
|
end
|
|
27
27
|
end
|
|
28
28
|
end
|
|
29
29
|
|
|
30
|
-
context "when not given a
|
|
30
|
+
context "when not given a a set of preexisting marks" do
|
|
31
31
|
it "generates a NxN board of the given size" do
|
|
32
32
|
(3..5).each do |size|
|
|
33
|
-
custom_board =
|
|
33
|
+
custom_board = blank_board(size)
|
|
34
34
|
|
|
35
35
|
expect(custom_board.size).to eq size
|
|
36
36
|
expect(custom_board.all_coordinates.count).to eq size**2
|
|
@@ -38,23 +38,21 @@ module TicTacToe
|
|
|
38
38
|
end
|
|
39
39
|
|
|
40
40
|
it "leaves the generated board blank" do
|
|
41
|
-
expect(
|
|
41
|
+
expect(blank_board(@default_board_size).all_blank?).to be true
|
|
42
42
|
end
|
|
43
43
|
end
|
|
44
44
|
end
|
|
45
45
|
|
|
46
|
-
describe "#
|
|
47
|
-
it "gets the contents of
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
config[0] = mark
|
|
51
|
-
board = build_board(config)
|
|
46
|
+
describe "#read_space" do
|
|
47
|
+
it "gets the contents of space at given row and column" do
|
|
48
|
+
marked_spaces = [x, _, _, _, _, _, _, _, _]
|
|
49
|
+
board = build_board(marked_spaces)
|
|
52
50
|
|
|
53
|
-
expect(board.
|
|
51
|
+
expect(board.read_space([0, 0])).to eq x
|
|
54
52
|
end
|
|
55
53
|
end
|
|
56
54
|
|
|
57
|
-
describe "#
|
|
55
|
+
describe "#mark_space" do
|
|
58
56
|
let(:board) { blank_board(@default_board_size) }
|
|
59
57
|
let(:coordinates) { random_coordinates(board.size) }
|
|
60
58
|
let(:mark) { @default_player_marks.sample }
|
|
@@ -62,19 +60,19 @@ module TicTacToe
|
|
|
62
60
|
it "returns a new board with the given coordinates played" do
|
|
63
61
|
board = blank_board(@default_board_size)
|
|
64
62
|
|
|
65
|
-
expect(board.
|
|
63
|
+
expect(board.mark_space(mark, coordinates).read_space(coordinates)).to eq(mark)
|
|
66
64
|
end
|
|
67
65
|
|
|
68
66
|
it "does not mutate the board" do
|
|
69
67
|
board = blank_board(@default_board_size)
|
|
70
68
|
|
|
71
|
-
board.
|
|
69
|
+
board.mark_space(mark, coordinates)
|
|
72
70
|
|
|
73
71
|
expect(board).to be_all_blank
|
|
74
72
|
end
|
|
75
73
|
|
|
76
74
|
it "records the coordinates of the last mark made" do
|
|
77
|
-
returned_board = board.
|
|
75
|
+
returned_board = board.mark_space(mark, coordinates)
|
|
78
76
|
|
|
79
77
|
expect(returned_board.last_move_made).to eq coordinates
|
|
80
78
|
end
|
|
@@ -96,33 +94,33 @@ module TicTacToe
|
|
|
96
94
|
describe "#all_coordinates" do
|
|
97
95
|
let(:board) { blank_board(@default_board_size) }
|
|
98
96
|
|
|
99
|
-
it "returns the coordinates of every
|
|
97
|
+
it "returns the coordinates of every space in board" do
|
|
100
98
|
all_coordinates = (0...board.size).to_a.repeated_permutation(2).to_a
|
|
101
99
|
|
|
102
100
|
expect(board.all_coordinates).to match_array all_coordinates
|
|
103
101
|
end
|
|
104
102
|
end
|
|
105
103
|
|
|
106
|
-
describe "#
|
|
107
|
-
it "returns all
|
|
104
|
+
describe "#blank_space_coordinates" do
|
|
105
|
+
it "returns all space coordinates when board is blank" do
|
|
108
106
|
board = blank_board(@default_board_size)
|
|
109
107
|
|
|
110
|
-
expect(board.
|
|
108
|
+
expect(board.blank_space_coordinates).to match_array board.all_coordinates
|
|
111
109
|
end
|
|
112
110
|
|
|
113
|
-
it "returns the coordinates of all blank
|
|
114
|
-
|
|
115
|
-
board = build_board(
|
|
111
|
+
it "returns the coordinates of all blank spaces in board" do
|
|
112
|
+
marked_spaces = [x, o, _, _, _, _, _, _, _].shuffle
|
|
113
|
+
board = build_board(marked_spaces)
|
|
116
114
|
unmarked_coordinates = board.all_coordinates.reject { |coords| board.marked?(coords) }
|
|
117
115
|
|
|
118
|
-
expect(board.
|
|
116
|
+
expect(board.blank_space_coordinates).to match_array unmarked_coordinates
|
|
119
117
|
end
|
|
120
118
|
|
|
121
|
-
it "returns no coordinates when no
|
|
122
|
-
|
|
123
|
-
board = build_board(
|
|
119
|
+
it "returns no coordinates when no spaces are blank" do
|
|
120
|
+
marked_spaces = [x, o, x, o, x, o, x, o, x].shuffle
|
|
121
|
+
board = build_board(marked_spaces)
|
|
124
122
|
|
|
125
|
-
expect(board.
|
|
123
|
+
expect(board.blank_space_coordinates.count).to eq 0
|
|
126
124
|
end
|
|
127
125
|
end
|
|
128
126
|
|
|
@@ -137,7 +135,7 @@ module TicTacToe
|
|
|
137
135
|
it "returns the last mark made on the board" do
|
|
138
136
|
board = blank_board(@default_board_size)
|
|
139
137
|
mark = @default_player_marks.sample
|
|
140
|
-
returned_board = board.
|
|
138
|
+
returned_board = board.mark_space(mark, random_coordinates(board.size))
|
|
141
139
|
|
|
142
140
|
expect(returned_board.last_mark_made).to eq mark
|
|
143
141
|
end
|
|
@@ -145,31 +143,31 @@ module TicTacToe
|
|
|
145
143
|
end
|
|
146
144
|
|
|
147
145
|
describe "#blank?" do
|
|
148
|
-
it "returns true if
|
|
146
|
+
it "returns true if space at given coordinates is blank" do
|
|
149
147
|
board = blank_board(@default_board_size)
|
|
150
148
|
|
|
151
149
|
expect(board.blank?(random_coordinates(board.size))).to be true
|
|
152
150
|
end
|
|
153
151
|
|
|
154
|
-
it "returns false if
|
|
152
|
+
it "returns false if space at given coordinates is not blank" do
|
|
155
153
|
board = blank_board(@default_board_size)
|
|
156
154
|
coordinates = random_coordinates(board.size)
|
|
157
|
-
returned_board = board.
|
|
155
|
+
returned_board = board.mark_space(@default_player_marks.sample, coordinates)
|
|
158
156
|
|
|
159
157
|
expect(returned_board.blank?(coordinates)).to be false
|
|
160
158
|
end
|
|
161
159
|
end
|
|
162
160
|
|
|
163
161
|
describe "#marked?" do
|
|
164
|
-
it "returns true if
|
|
162
|
+
it "returns true if space at given coordinates has any player's mark" do
|
|
165
163
|
board = blank_board(@default_board_size)
|
|
166
164
|
coordinates = random_coordinates(board.size)
|
|
167
|
-
returned_board = board.
|
|
165
|
+
returned_board = board.mark_space(@default_player_marks.sample, coordinates)
|
|
168
166
|
|
|
169
167
|
expect(returned_board.marked?(coordinates)).to be true
|
|
170
168
|
end
|
|
171
169
|
|
|
172
|
-
it "returns false if
|
|
170
|
+
it "returns false if space at given coordinates does not have a player's mark" do
|
|
173
171
|
blank_board = blank_board(@default_board_size)
|
|
174
172
|
coordinates = random_coordinates(blank_board.size)
|
|
175
173
|
|
|
@@ -195,31 +193,31 @@ module TicTacToe
|
|
|
195
193
|
end
|
|
196
194
|
|
|
197
195
|
describe "#all_blank?" do
|
|
198
|
-
it "returns true if no
|
|
196
|
+
it "returns true if no space in board is marked" do
|
|
199
197
|
board = blank_board(@default_board_size)
|
|
200
198
|
|
|
201
199
|
expect(board.all_blank?).to be true
|
|
202
200
|
end
|
|
203
201
|
|
|
204
|
-
it "returns false if any
|
|
205
|
-
|
|
206
|
-
board = build_board(
|
|
202
|
+
it "returns false if any space in board is marked" do
|
|
203
|
+
marked_spaces = [x, _, _, _, _, _, _, _, _].shuffle
|
|
204
|
+
board = build_board(marked_spaces)
|
|
207
205
|
|
|
208
206
|
expect(board.all_blank?).to be false
|
|
209
207
|
end
|
|
210
208
|
end
|
|
211
209
|
|
|
212
210
|
describe "#all_marked?" do
|
|
213
|
-
it "returns true if all
|
|
214
|
-
|
|
215
|
-
board = build_board(
|
|
211
|
+
it "returns true if all spaces in board are marked" do
|
|
212
|
+
marked_spaces = [x, x, x, x, x, o, o, o, o].shuffle
|
|
213
|
+
board = build_board(marked_spaces)
|
|
216
214
|
|
|
217
215
|
expect(board.all_marked?).to be true
|
|
218
216
|
end
|
|
219
217
|
|
|
220
|
-
it "returns false if any
|
|
221
|
-
|
|
222
|
-
board = build_board(
|
|
218
|
+
it "returns false if any space in board is blank" do
|
|
219
|
+
marked_spaces = [x, x, x, x, _, o, o, o, o].shuffle
|
|
220
|
+
board = build_board(marked_spaces)
|
|
223
221
|
|
|
224
222
|
expect(board.all_marked?).to be false
|
|
225
223
|
end
|
|
@@ -227,7 +225,7 @@ module TicTacToe
|
|
|
227
225
|
|
|
228
226
|
describe "#has_winning_line?" do
|
|
229
227
|
it "returns true if board has a horizontal winning line" do
|
|
230
|
-
|
|
228
|
+
winning_configurations = [
|
|
231
229
|
[ x, x, x,
|
|
232
230
|
_, _, _,
|
|
233
231
|
_, _, _ ],
|
|
@@ -239,13 +237,13 @@ module TicTacToe
|
|
|
239
237
|
x, x, x ]
|
|
240
238
|
]
|
|
241
239
|
|
|
242
|
-
|
|
243
|
-
expect(build_board(
|
|
240
|
+
winning_configurations.each do |marked_spaces|
|
|
241
|
+
expect(build_board(marked_spaces).has_winning_line?).to be true
|
|
244
242
|
end
|
|
245
243
|
end
|
|
246
244
|
|
|
247
245
|
it "returns true if board has a vertical winning line" do
|
|
248
|
-
|
|
246
|
+
winning_configurations = [
|
|
249
247
|
[ x, _, _,
|
|
250
248
|
x, _, _,
|
|
251
249
|
x, _, _ ],
|
|
@@ -257,13 +255,13 @@ module TicTacToe
|
|
|
257
255
|
_, _, x ]
|
|
258
256
|
]
|
|
259
257
|
|
|
260
|
-
|
|
261
|
-
expect(build_board(
|
|
258
|
+
winning_configurations.each do |marked_spaces|
|
|
259
|
+
expect(build_board(marked_spaces).has_winning_line?).to be true
|
|
262
260
|
end
|
|
263
261
|
end
|
|
264
262
|
|
|
265
263
|
it "returns true if board has a diagonal winning line" do
|
|
266
|
-
|
|
264
|
+
winning_configurations = [
|
|
267
265
|
[ x, _, _,
|
|
268
266
|
_, x, _,
|
|
269
267
|
_, _, x ],
|
|
@@ -272,13 +270,13 @@ module TicTacToe
|
|
|
272
270
|
x, _, _ ]
|
|
273
271
|
]
|
|
274
272
|
|
|
275
|
-
|
|
276
|
-
expect(build_board(
|
|
273
|
+
winning_configurations.each do |marked_spaces|
|
|
274
|
+
expect(build_board(marked_spaces).has_winning_line?).to be true
|
|
277
275
|
end
|
|
278
276
|
end
|
|
279
277
|
|
|
280
278
|
it "returns false if board has no winning line" do
|
|
281
|
-
|
|
279
|
+
non_winning_configurations = [
|
|
282
280
|
[ _, _, _,
|
|
283
281
|
_, _, _,
|
|
284
282
|
_, _, _ ],
|
|
@@ -296,8 +294,8 @@ module TicTacToe
|
|
|
296
294
|
o, x, o ]
|
|
297
295
|
]
|
|
298
296
|
|
|
299
|
-
|
|
300
|
-
expect(build_board(
|
|
297
|
+
non_winning_configurations.each do |marked_spaces|
|
|
298
|
+
expect(build_board(marked_spaces).has_winning_line?).to be false
|
|
301
299
|
end
|
|
302
300
|
end
|
|
303
301
|
end
|
|
@@ -15,6 +15,11 @@ module TicTacToe
|
|
|
15
15
|
CommandLineInterface.new(parameters)
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
+
def at_least_one_repeated_line?(string)
|
|
19
|
+
lines = string.split("\n")
|
|
20
|
+
lines.uniq.length < lines.length
|
|
21
|
+
end
|
|
22
|
+
|
|
18
23
|
describe "#game_setup_interaction" do
|
|
19
24
|
before do
|
|
20
25
|
input_stream.string = %w(human computer).join("\n")
|
|
@@ -41,7 +46,7 @@ module TicTacToe
|
|
|
41
46
|
|
|
42
47
|
it "prints a prompt to the command line" do
|
|
43
48
|
input_stream.string = valid_input
|
|
44
|
-
interface.solicit_player_type(@
|
|
49
|
+
interface.solicit_player_type(@default_player_marks.first)
|
|
45
50
|
|
|
46
51
|
expect(output_stream.string).not_to eq ""
|
|
47
52
|
end
|
|
@@ -50,7 +55,7 @@ module TicTacToe
|
|
|
50
55
|
it "returns the player type input by user" do
|
|
51
56
|
input_stream.string = valid_input
|
|
52
57
|
|
|
53
|
-
expect(interface.solicit_player_type(@
|
|
58
|
+
expect(interface.solicit_player_type(@default_player_marks.first)).to eq valid_input.to_sym
|
|
54
59
|
end
|
|
55
60
|
end
|
|
56
61
|
|
|
@@ -59,7 +64,7 @@ module TicTacToe
|
|
|
59
64
|
|
|
60
65
|
it "prompts the user until given valid input" do
|
|
61
66
|
input_stream.string = invalid_input + "\n" + invalid_input + "\n" + valid_input
|
|
62
|
-
interface.solicit_player_type(@
|
|
67
|
+
interface.solicit_player_type(@default_player_marks.first)
|
|
63
68
|
|
|
64
69
|
expect(at_least_one_repeated_line?(output_stream.string)).to be true
|
|
65
70
|
end
|
|
@@ -67,17 +72,17 @@ module TicTacToe
|
|
|
67
72
|
end
|
|
68
73
|
|
|
69
74
|
describe "#show_game_board" do
|
|
75
|
+
let(:_) { Board::BLANK_MARK }
|
|
76
|
+
let(:x) { @default_player_marks.first }
|
|
77
|
+
let(:o) { @default_player_marks.last }
|
|
78
|
+
|
|
70
79
|
it "prints a respresentation of the given board to the command line" do
|
|
71
|
-
board =
|
|
80
|
+
board = build_board([x, x, x, o, o, o, _, _, _])
|
|
72
81
|
interface.show_game_board(board)
|
|
73
|
-
|
|
74
82
|
board_characters = output_stream.string.split("")
|
|
75
|
-
cell_count = board.size**2
|
|
76
|
-
expected_first_mark_count = cell_count.odd? ? cell_count / 2 + 1 : cell_count / 2
|
|
77
|
-
expected_second_mark_count = cell_count / 2
|
|
78
83
|
|
|
79
|
-
expect(board_characters.count(
|
|
80
|
-
expect(board_characters.count(
|
|
84
|
+
expect(board_characters.count(x.to_s)).to eq 3
|
|
85
|
+
expect(board_characters.count(o.to_s)).to eq 3
|
|
81
86
|
end
|
|
82
87
|
end
|
|
83
88
|
|
|
@@ -86,7 +91,7 @@ module TicTacToe
|
|
|
86
91
|
|
|
87
92
|
it "prints a prompt to the command line" do
|
|
88
93
|
input_stream.string = valid_input
|
|
89
|
-
interface.solicit_move(@
|
|
94
|
+
interface.solicit_move(@default_player_marks.first)
|
|
90
95
|
|
|
91
96
|
expect(output_stream.string).not_to eq ""
|
|
92
97
|
end
|
|
@@ -96,7 +101,7 @@ module TicTacToe
|
|
|
96
101
|
input_stream.string = valid_input
|
|
97
102
|
valid_coordinate = valid_input.split(",").map(&:to_i)
|
|
98
103
|
|
|
99
|
-
expect(interface.solicit_move(@
|
|
104
|
+
expect(interface.solicit_move(@default_player_marks.first)).to eq valid_coordinate
|
|
100
105
|
end
|
|
101
106
|
end
|
|
102
107
|
|
|
@@ -105,7 +110,7 @@ module TicTacToe
|
|
|
105
110
|
|
|
106
111
|
it "prompts the user until given valid input" do
|
|
107
112
|
input_stream.string = invalid_input + "\n" + invalid_input + "\n" + valid_input
|
|
108
|
-
interface.solicit_move(@
|
|
113
|
+
interface.solicit_move(@default_player_marks.first)
|
|
109
114
|
|
|
110
115
|
expect(at_least_one_repeated_line?(output_stream.string)).to be true
|
|
111
116
|
end
|
|
@@ -122,10 +127,10 @@ module TicTacToe
|
|
|
122
127
|
|
|
123
128
|
describe "#report_move" do
|
|
124
129
|
it "prints a notification of the move made by the given mark at the given coordinates" do
|
|
125
|
-
interface.report_move(@
|
|
130
|
+
interface.report_move(@default_player_marks.first, [0, 0])
|
|
126
131
|
interface_output = output_stream.string
|
|
127
132
|
|
|
128
|
-
expect(interface_output).to include @
|
|
133
|
+
expect(interface_output).to include @default_player_marks.first.to_s
|
|
129
134
|
expect(interface_output.split("").count("0")).to eq 2
|
|
130
135
|
end
|
|
131
136
|
end
|
|
@@ -133,8 +138,8 @@ module TicTacToe
|
|
|
133
138
|
describe "#report_game_over" do
|
|
134
139
|
context "when given the mark of a winning player" do
|
|
135
140
|
it "prints a notification that the player has won" do
|
|
136
|
-
expect(interface).to receive(:report_win).with(@
|
|
137
|
-
interface.report_game_over(@
|
|
141
|
+
expect(interface).to receive(:report_win).with(@default_player_marks.first)
|
|
142
|
+
interface.report_game_over(@default_player_marks.first)
|
|
138
143
|
end
|
|
139
144
|
end
|
|
140
145
|
|
|
@@ -148,10 +153,10 @@ module TicTacToe
|
|
|
148
153
|
|
|
149
154
|
describe "#report_win" do
|
|
150
155
|
it "prints a notification that the player using the given mark has won" do
|
|
151
|
-
interface.report_win(@
|
|
156
|
+
interface.report_win(@default_player_marks.first)
|
|
152
157
|
interface_output = output_stream.string
|
|
153
158
|
|
|
154
|
-
expect(interface_output).to include @
|
|
159
|
+
expect(interface_output).to include @default_player_marks.first.to_s
|
|
155
160
|
expect(interface_output).to include "wins"
|
|
156
161
|
end
|
|
157
162
|
end
|
|
@@ -10,8 +10,8 @@ module TicTacToe
|
|
|
10
10
|
include_context "helper_methods"
|
|
11
11
|
|
|
12
12
|
let(:_) { Board::BLANK_MARK }
|
|
13
|
-
let(:x) { @
|
|
14
|
-
let(:o) { @
|
|
13
|
+
let(:x) { @default_player_marks.first }
|
|
14
|
+
let(:o) { @default_player_marks.last }
|
|
15
15
|
|
|
16
16
|
def new_computer_player(parameters)
|
|
17
17
|
ComputerPlayer.new(parameters)
|
|
@@ -37,12 +37,12 @@ module TicTacToe
|
|
|
37
37
|
|
|
38
38
|
describe "#move" do
|
|
39
39
|
it "returns the coordinates of a valid move" do
|
|
40
|
-
|
|
40
|
+
marked_spaces = [
|
|
41
41
|
x, o, x,
|
|
42
42
|
x, x, o,
|
|
43
43
|
o, _, _
|
|
44
44
|
]
|
|
45
|
-
board = build_board(
|
|
45
|
+
board = build_board(marked_spaces).mark_space(o, [2, 1])
|
|
46
46
|
game = Game.new(board: board)
|
|
47
47
|
computer_player = x_player(board)
|
|
48
48
|
coordinates = computer_player.move(game)
|
|
@@ -64,7 +64,7 @@ module TicTacToe
|
|
|
64
64
|
|
|
65
65
|
context "when computer player can make a horizontal winning move" do
|
|
66
66
|
it "returns the coordinates of the winning move" do
|
|
67
|
-
|
|
67
|
+
board_configurations = [
|
|
68
68
|
[ x, _, x,
|
|
69
69
|
_, o, _,
|
|
70
70
|
o, x, o ],
|
|
@@ -76,8 +76,8 @@ module TicTacToe
|
|
|
76
76
|
_, x, x ]
|
|
77
77
|
]
|
|
78
78
|
winning_moves = [[0, 1], [1, 2], [2, 0]]
|
|
79
|
-
|
|
80
|
-
board = build_board(
|
|
79
|
+
board_configurations.zip(winning_moves).each do |marked_spaces, winning_move|
|
|
80
|
+
board = build_board(marked_spaces)
|
|
81
81
|
game = Game.new(board: board)
|
|
82
82
|
computer_player = x_player(board)
|
|
83
83
|
|
|
@@ -88,7 +88,7 @@ module TicTacToe
|
|
|
88
88
|
|
|
89
89
|
context "when computer player can make a vertical winning move" do
|
|
90
90
|
it "returns the coordinates of the winning move" do
|
|
91
|
-
|
|
91
|
+
board_configurations = [
|
|
92
92
|
[ x, _, o,
|
|
93
93
|
_, o, x,
|
|
94
94
|
x, _, o ],
|
|
@@ -100,8 +100,8 @@ module TicTacToe
|
|
|
100
100
|
o, x, x ]
|
|
101
101
|
]
|
|
102
102
|
winning_moves = [[1, 0], [2, 1], [0, 2]]
|
|
103
|
-
|
|
104
|
-
board = build_board(
|
|
103
|
+
board_configurations.zip(winning_moves).each do |marked_spaces, winning_move|
|
|
104
|
+
board = build_board(marked_spaces)
|
|
105
105
|
game = Game.new(board: board)
|
|
106
106
|
computer_player = x_player(board)
|
|
107
107
|
|
|
@@ -112,7 +112,7 @@ module TicTacToe
|
|
|
112
112
|
|
|
113
113
|
context "when computer player can make a diagonal winning move" do
|
|
114
114
|
it "returns the coordinates of the winning move" do
|
|
115
|
-
|
|
115
|
+
board_configurations = [
|
|
116
116
|
[ x, _, o,
|
|
117
117
|
o, x, _,
|
|
118
118
|
x, o, _ ],
|
|
@@ -121,8 +121,8 @@ module TicTacToe
|
|
|
121
121
|
x, o, _ ]
|
|
122
122
|
]
|
|
123
123
|
winning_moves = [[2, 2], [0, 2]]
|
|
124
|
-
|
|
125
|
-
board = build_board(
|
|
124
|
+
board_configurations.zip(winning_moves).each do |marked_spaces, winning_move|
|
|
125
|
+
board = build_board(marked_spaces)
|
|
126
126
|
computer_player = x_player(board)
|
|
127
127
|
game = Game.new(board: board)
|
|
128
128
|
|
|
@@ -133,7 +133,7 @@ module TicTacToe
|
|
|
133
133
|
|
|
134
134
|
context "when opponent can make a horizontal winning move next turn" do
|
|
135
135
|
it "returns the coordinates of the move that blocks the opponent from winning" do
|
|
136
|
-
|
|
136
|
+
board_configurations = [
|
|
137
137
|
[ x, _, x,
|
|
138
138
|
_, o, _,
|
|
139
139
|
o, x, o ],
|
|
@@ -145,8 +145,8 @@ module TicTacToe
|
|
|
145
145
|
_, x, x ]
|
|
146
146
|
]
|
|
147
147
|
winning_moves = [[0, 1], [1, 2], [2, 0]]
|
|
148
|
-
|
|
149
|
-
board = build_board(
|
|
148
|
+
board_configurations.zip(winning_moves).each do |marked_spaces, winning_move|
|
|
149
|
+
board = build_board(marked_spaces)
|
|
150
150
|
computer_player = o_player(board)
|
|
151
151
|
game = Game.new(board: board)
|
|
152
152
|
|
|
@@ -157,7 +157,7 @@ module TicTacToe
|
|
|
157
157
|
|
|
158
158
|
context "when opponent can make a vertical winning move next turn" do
|
|
159
159
|
it "returns the coordinates of the move that blocks the opponent from winning" do
|
|
160
|
-
|
|
160
|
+
board_configurations = [
|
|
161
161
|
[ x, _, o,
|
|
162
162
|
_, o, x,
|
|
163
163
|
x, _, o ],
|
|
@@ -169,8 +169,8 @@ module TicTacToe
|
|
|
169
169
|
o, x, x ]
|
|
170
170
|
]
|
|
171
171
|
winning_moves = [[1, 0], [2, 1], [0, 2]]
|
|
172
|
-
|
|
173
|
-
board = build_board(
|
|
172
|
+
board_configurations.zip(winning_moves).each do |marked_spaces, winning_move|
|
|
173
|
+
board = build_board(marked_spaces)
|
|
174
174
|
computer_player = o_player(board)
|
|
175
175
|
game = Game.new(board: board)
|
|
176
176
|
|
|
@@ -181,7 +181,7 @@ module TicTacToe
|
|
|
181
181
|
|
|
182
182
|
context "when opponent can make a diagonal winning move next turn" do
|
|
183
183
|
it "returns the coordinates of the move that blocks the opponent from winning" do
|
|
184
|
-
|
|
184
|
+
board_configurations = [
|
|
185
185
|
[ x, _, o,
|
|
186
186
|
o, x, _,
|
|
187
187
|
x, o, _ ],
|
|
@@ -190,8 +190,8 @@ module TicTacToe
|
|
|
190
190
|
x, o, _ ]
|
|
191
191
|
]
|
|
192
192
|
winning_moves = [[2, 2], [0, 2]]
|
|
193
|
-
|
|
194
|
-
board = build_board(
|
|
193
|
+
board_configurations.zip(winning_moves).each do |marked_spaces, winning_move|
|
|
194
|
+
board = build_board(marked_spaces)
|
|
195
195
|
computer_player = o_player(board)
|
|
196
196
|
game = Game.new(board: board)
|
|
197
197
|
|
|
@@ -202,7 +202,7 @@ module TicTacToe
|
|
|
202
202
|
|
|
203
203
|
context "when opponent can make a fork next turn" do
|
|
204
204
|
it "returns the coordinates of a move that prevents that fork" do
|
|
205
|
-
|
|
205
|
+
board_configurations = [
|
|
206
206
|
[ x, _, _,
|
|
207
207
|
_, x, _,
|
|
208
208
|
_, _, o ],
|
|
@@ -218,8 +218,8 @@ module TicTacToe
|
|
|
218
218
|
[[0, 1], [1, 0], [1, 2], [2, 1]],
|
|
219
219
|
[[0, 0], [0, 2], [2, 0], [2, 2]]
|
|
220
220
|
]
|
|
221
|
-
|
|
222
|
-
board = build_board(
|
|
221
|
+
board_configurations.zip(good_move_sets).each do |marked_spaces, good_moves|
|
|
222
|
+
board = build_board(marked_spaces)
|
|
223
223
|
computer_player = o_player(board)
|
|
224
224
|
game = Game.new(board: board)
|
|
225
225
|
|
data/spec/game_spec.rb
CHANGED
|
@@ -114,7 +114,7 @@ module TicTacToe
|
|
|
114
114
|
let(:player_stub) { Object.new }
|
|
115
115
|
|
|
116
116
|
before do
|
|
117
|
-
allow(player_stub).to receive(:player_mark).and_return(@
|
|
117
|
+
allow(player_stub).to receive(:player_mark).and_return(@default_player_marks.first)
|
|
118
118
|
allow(player_stub).to receive(:move).and_return([0, 0])
|
|
119
119
|
end
|
|
120
120
|
|
|
@@ -138,13 +138,13 @@ module TicTacToe
|
|
|
138
138
|
allow(game.interface).to receive(:report_move)
|
|
139
139
|
game.handle_one_turn(player_stub)
|
|
140
140
|
|
|
141
|
-
expect(game.board.
|
|
141
|
+
expect(game.board.read_space([0, 0])).to eq @default_player_marks.first
|
|
142
142
|
end
|
|
143
143
|
|
|
144
144
|
it "reports the move that was just made through the interface" do
|
|
145
145
|
allow(game.interface).to receive(:show_game_board)
|
|
146
146
|
|
|
147
|
-
expect(game.interface).to receive(:report_move).with(@
|
|
147
|
+
expect(game.interface).to receive(:report_move).with(@default_player_marks.first, [0, 0])
|
|
148
148
|
game.handle_one_turn(player_stub)
|
|
149
149
|
end
|
|
150
150
|
end
|
|
@@ -206,9 +206,9 @@ module TicTacToe
|
|
|
206
206
|
it "reports that the given last player to move has won via the interface" do
|
|
207
207
|
allow(game.interface).to receive(:show_game_board)
|
|
208
208
|
allow(game.board).to receive(:has_winning_line?).and_return(true)
|
|
209
|
-
allow(game.board).to receive(:last_mark_made).and_return(@
|
|
209
|
+
allow(game.board).to receive(:last_mark_made).and_return(@default_player_marks.first)
|
|
210
210
|
|
|
211
|
-
expect(game.interface).to receive(:report_game_over).with(@
|
|
211
|
+
expect(game.interface).to receive(:report_game_over).with(@default_player_marks.first)
|
|
212
212
|
game.handle_game_over
|
|
213
213
|
end
|
|
214
214
|
end
|
|
@@ -216,7 +216,7 @@ module TicTacToe
|
|
|
216
216
|
context "when game has no winner" do
|
|
217
217
|
it "reports that game ended in a draw via the interface" do
|
|
218
218
|
allow(game.interface).to receive(:show_game_board)
|
|
219
|
-
allow(game.board).to receive(:last_mark_made).and_return(@
|
|
219
|
+
allow(game.board).to receive(:last_mark_made).and_return(@default_player_marks.first)
|
|
220
220
|
|
|
221
221
|
expect(game.interface).to receive(:report_game_over).with(:none)
|
|
222
222
|
game.handle_game_over
|
|
@@ -277,7 +277,7 @@ module TicTacToe
|
|
|
277
277
|
|
|
278
278
|
it "should end in a win for the computer player against an unskilled human player" do
|
|
279
279
|
allow(game.interface).to receive(:solicit_move) do
|
|
280
|
-
game.board.
|
|
280
|
+
game.board.blank_space_coordinates.first
|
|
281
281
|
end
|
|
282
282
|
computer_player_mark = :o
|
|
283
283
|
game.run
|
data/spec/human_player_spec.rb
CHANGED
data/spec/player_factory_spec.rb
CHANGED
|
@@ -10,38 +10,38 @@ module TicTacToe
|
|
|
10
10
|
describe ".build" do
|
|
11
11
|
let(:player_types) { [AvailablePlayerTypes::HUMAN, AvailablePlayerTypes::COMPUTER] }
|
|
12
12
|
let(:player_classes) { [HumanPlayer, ComputerPlayer] }
|
|
13
|
-
let(:
|
|
13
|
+
let(:player_parameters) do
|
|
14
14
|
{
|
|
15
15
|
game: Game.new({}),
|
|
16
16
|
player_mark: @default_player_marks.first
|
|
17
17
|
}
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
-
def build_player(
|
|
21
|
-
PlayerFactory.build(
|
|
20
|
+
def build_player(player_parameters)
|
|
21
|
+
PlayerFactory.build(player_parameters)
|
|
22
22
|
end
|
|
23
23
|
|
|
24
24
|
it "creates a player of the given type" do
|
|
25
25
|
player_types.zip(player_classes).each do |type, player_class|
|
|
26
|
-
|
|
26
|
+
player_parameters[:type] = type
|
|
27
27
|
|
|
28
|
-
expect(build_player(
|
|
28
|
+
expect(build_player(player_parameters)).to be_a player_class
|
|
29
29
|
end
|
|
30
30
|
end
|
|
31
31
|
|
|
32
32
|
it "creates players that respond to #move" do
|
|
33
33
|
player_types.each do |type|
|
|
34
|
-
|
|
34
|
+
player_parameters[:type] = type
|
|
35
35
|
|
|
36
|
-
expect(build_player(
|
|
36
|
+
expect(build_player(player_parameters)).to respond_to :move
|
|
37
37
|
end
|
|
38
38
|
end
|
|
39
39
|
|
|
40
40
|
it "creates players that use the given mark" do
|
|
41
41
|
player_types.each do |type|
|
|
42
|
-
|
|
42
|
+
player_parameters[:type] = type
|
|
43
43
|
|
|
44
|
-
expect(build_player(
|
|
44
|
+
expect(build_player(player_parameters).player_mark).to eq player_parameters[:player_mark]
|
|
45
45
|
end
|
|
46
46
|
end
|
|
47
47
|
end
|
data/spec/spec_helper.rb
CHANGED
|
@@ -4,8 +4,6 @@ require "rspec/collection_matchers"
|
|
|
4
4
|
RSpec.shared_context "default_values" do
|
|
5
5
|
before :all do
|
|
6
6
|
@default_board_size = 3
|
|
7
|
-
@default_first_player = :x
|
|
8
|
-
@default_second_player = :o
|
|
9
7
|
@default_player_marks = [:x, :o]
|
|
10
8
|
@default_player_types = [
|
|
11
9
|
TicTacToe::AvailablePlayerTypes::HUMAN,
|
|
@@ -15,42 +13,15 @@ RSpec.shared_context "default_values" do
|
|
|
15
13
|
end
|
|
16
14
|
|
|
17
15
|
RSpec.shared_context "helper_methods" do
|
|
18
|
-
def blank_board_configuration(board_size)
|
|
19
|
-
(0...board_size**2).map { TicTacToe::Board::BLANK_MARK }
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def at_least_one_repeated_line?(string)
|
|
23
|
-
lines = string.split("\n")
|
|
24
|
-
lines.uniq.length < lines.length
|
|
25
|
-
end
|
|
26
|
-
|
|
27
16
|
def random_coordinates(board_size)
|
|
28
17
|
[rand(board_size), rand(board_size)]
|
|
29
18
|
end
|
|
30
19
|
|
|
31
|
-
def
|
|
32
|
-
TicTacToe::Board.new(
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
def build_board(config)
|
|
36
|
-
size = Math.sqrt(config.size).to_i
|
|
37
|
-
new_board(size: size, config: config)
|
|
20
|
+
def build_board(marked_spaces)
|
|
21
|
+
TicTacToe::Board.new(marked_spaces: marked_spaces)
|
|
38
22
|
end
|
|
39
23
|
|
|
40
24
|
def blank_board(board_size)
|
|
41
|
-
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
def board_with_draw(board_size, player_marks)
|
|
45
|
-
first_mark, second_mark = player_marks
|
|
46
|
-
blank_board(board_size).blank_cell_coordinates.reduce(blank_board(board_size)) do |board, (row, col)|
|
|
47
|
-
if row == 0
|
|
48
|
-
mark = col.odd? ? first_mark : second_mark
|
|
49
|
-
board.mark_cell(mark, row, col)
|
|
50
|
-
else
|
|
51
|
-
mark = col.even? ? first_mark : second_mark
|
|
52
|
-
board.mark_cell(mark, row, col)
|
|
53
|
-
end
|
|
54
|
-
end
|
|
25
|
+
TicTacToe::Board.new(size: board_size)
|
|
55
26
|
end
|
|
56
27
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: tactical_tic_tac_toe
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 1.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Batman
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2015-
|
|
11
|
+
date: 2015-11-01 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: Command line tic tac toe! Run with command 'ttt'
|
|
14
14
|
email: no@no.no
|