mastermind-cmdline 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/bin/mastermind +9 -0
- data/lib/mastermind.rb +70 -0
- data/lib/mastermind/AIsolver.rb +36 -0
- data/lib/mastermind/GameRules.rb +73 -0
- data/lib/mastermind/GameStatus.rb +52 -0
- data/lib/mastermind/TerminalInterface.rb +37 -0
- data/lib/mastermind/UserInterface.rb +25 -0
- data/test/mastermind_spec.rb +256 -0
- metadata +53 -0
data/bin/mastermind
ADDED
data/lib/mastermind.rb
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
require_relative './mastermind/GameRules'
|
2
|
+
require_relative './mastermind/TerminalInterface'
|
3
|
+
require_relative './mastermind/GameStatus'
|
4
|
+
require_relative './mastermind/AIsolver'
|
5
|
+
|
6
|
+
module Mastermind
|
7
|
+
class Game
|
8
|
+
def initialize(game_text, terminal)
|
9
|
+
@game_text = game_text
|
10
|
+
@terminal = terminal
|
11
|
+
@code_length = 4
|
12
|
+
end
|
13
|
+
|
14
|
+
def play_game
|
15
|
+
@terminal.display(@game_text.message(:welcome))
|
16
|
+
colors = get_color_scheme
|
17
|
+
code = get_input(colors)
|
18
|
+
set_up_board(code, colors)
|
19
|
+
result = run_ai_player(colors)
|
20
|
+
end_of_game(result)
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def get_color_scheme
|
26
|
+
@terminal.display(@game_text.message(:color_scheme))
|
27
|
+
colors = @terminal.formatted_input
|
28
|
+
Colors.new(colors).valid_colors
|
29
|
+
end
|
30
|
+
|
31
|
+
def get_input(colors)
|
32
|
+
@terminal.display(@game_text.message(:prompt) )
|
33
|
+
input = @terminal.formatted_input
|
34
|
+
unless Validator.new(input, @code_length, colors ).valid?
|
35
|
+
get_input
|
36
|
+
else
|
37
|
+
input
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def set_up_board(code, colors)
|
42
|
+
@board = GameStatus.new(code, colors)
|
43
|
+
end
|
44
|
+
|
45
|
+
def run_ai_player(colors)
|
46
|
+
algorithm = NaiveAlgorithm.new(colors)
|
47
|
+
player = AIPlayer.new(@board, algorithm)
|
48
|
+
result = player.solve
|
49
|
+
until @board.end_of_game?(result)
|
50
|
+
result = player.solve
|
51
|
+
print_guess(result)
|
52
|
+
end
|
53
|
+
print_guess(result)
|
54
|
+
result
|
55
|
+
end
|
56
|
+
|
57
|
+
def print_guess(result)
|
58
|
+
@terminal.display(@game_text.message(:guess, result))
|
59
|
+
end
|
60
|
+
|
61
|
+
def end_of_game(result)
|
62
|
+
if(result.correct?)
|
63
|
+
@terminal.display(@game_text.message(:win, result))
|
64
|
+
else
|
65
|
+
@terminal.display(@game_text.message(:lose, result))
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Mastermind
|
2
|
+
class NaiveAlgorithm
|
3
|
+
attr_accessor :possible_guesses
|
4
|
+
|
5
|
+
def initialize(valid_letters)
|
6
|
+
@valid_letters = valid_letters
|
7
|
+
@possible_guesses = valid_letters.repeated_permutation(4).to_a
|
8
|
+
end
|
9
|
+
|
10
|
+
def next_guess
|
11
|
+
@possible_guesses[rand(@possible_guesses.size)]
|
12
|
+
end
|
13
|
+
|
14
|
+
def discard_invalid_guesses(incorrect_guess)
|
15
|
+
discarded_guesses = @possible_guesses.select do |guess|
|
16
|
+
compare_result = CodeComparer.new(incorrect_guess.guess, guess).compare
|
17
|
+
compare_result != incorrect_guess.result_hash
|
18
|
+
end
|
19
|
+
@possible_guesses -= discarded_guesses
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class AIPlayer
|
24
|
+
def initialize(board, algorithm)
|
25
|
+
@board = board
|
26
|
+
@algorithm = algorithm
|
27
|
+
end
|
28
|
+
|
29
|
+
def solve
|
30
|
+
next_guess = @algorithm.next_guess
|
31
|
+
result = @board.process_guess(next_guess)
|
32
|
+
@algorithm.discard_invalid_guesses(result)
|
33
|
+
result
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module Mastermind
|
2
|
+
DEFAULT_COLORS = %w{R G O Y B P}
|
3
|
+
class CodeComparer
|
4
|
+
def initialize(code, guess)
|
5
|
+
@code = code
|
6
|
+
@guess = guess
|
7
|
+
end
|
8
|
+
|
9
|
+
def compare
|
10
|
+
correct_colors = total_correct_colors - correct_positions
|
11
|
+
{
|
12
|
+
correct_positions: correct_positions,
|
13
|
+
correct_colors: correct_colors
|
14
|
+
}
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def correct_positions
|
20
|
+
code_with_indeces = @code.each_with_index.to_a
|
21
|
+
guess_with_indeces = @guess.each_with_index.to_a
|
22
|
+
intersection = code_with_indeces & guess_with_indeces
|
23
|
+
intersection.size
|
24
|
+
end
|
25
|
+
|
26
|
+
def total_correct_colors
|
27
|
+
correct_color = 0
|
28
|
+
@code.uniq.each do |letter|
|
29
|
+
correct_color += [@code.count(letter), @guess.count(letter)].min
|
30
|
+
end
|
31
|
+
correct_color
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class Validator
|
36
|
+
def initialize(code, code_length, valid_letters)
|
37
|
+
@code = code
|
38
|
+
@code_length = code_length
|
39
|
+
@valid_letters = valid_letters
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
def valid?
|
44
|
+
correct_length? && valid_letters?
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def correct_length?
|
50
|
+
@code.size == @code_length
|
51
|
+
end
|
52
|
+
|
53
|
+
def valid_letters?
|
54
|
+
@code.uniq.all? do |letter|
|
55
|
+
@valid_letters.include?letter
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
class Colors
|
61
|
+
def initialize(colors = [])
|
62
|
+
if(colors.empty? || colors.size != 6)
|
63
|
+
@colors = DEFAULT_COLORS
|
64
|
+
else
|
65
|
+
@colors = colors
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def valid_colors
|
70
|
+
@colors
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Mastermind
|
2
|
+
WIN_HASH = {correct_positions: 4, correct_colors:0}
|
3
|
+
|
4
|
+
class GameStatus
|
5
|
+
def initialize(code, colors)
|
6
|
+
@code = code
|
7
|
+
@num_of_tries = 0
|
8
|
+
@colors = colors
|
9
|
+
end
|
10
|
+
|
11
|
+
def valid_letters
|
12
|
+
@colors
|
13
|
+
end
|
14
|
+
|
15
|
+
def process_guess(guess)
|
16
|
+
@num_of_tries += 1
|
17
|
+
if win?(guess)
|
18
|
+
#Is it worth checking win separately here?
|
19
|
+
result_hash = WIN_HASH
|
20
|
+
else
|
21
|
+
result_hash = CodeComparer.new(@code, guess).compare
|
22
|
+
end
|
23
|
+
CurrentResult.new(guess, @num_of_tries, result_hash)
|
24
|
+
end
|
25
|
+
|
26
|
+
def end_of_game?(result)
|
27
|
+
win?(result.guess) || result.num_of_tries == 10
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def win?(guess)
|
34
|
+
@code == guess
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
class CurrentResult
|
39
|
+
attr_reader :result_hash
|
40
|
+
attr_reader :num_of_tries, :guess
|
41
|
+
|
42
|
+
def initialize(guess, num_of_tries, result_hash)
|
43
|
+
@guess = guess
|
44
|
+
@num_of_tries = num_of_tries
|
45
|
+
@result_hash = result_hash
|
46
|
+
end
|
47
|
+
|
48
|
+
def correct?
|
49
|
+
@result_hash == WIN_HASH
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Mastermind
|
2
|
+
class Terminal
|
3
|
+
def display(message)
|
4
|
+
puts message
|
5
|
+
end
|
6
|
+
|
7
|
+
def formatted_input(stdin = $stdin)
|
8
|
+
stdin.gets.upcase.split(%r{\s*} )
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class GameText
|
13
|
+
def message(message_type, game_result = [])
|
14
|
+
case message_type
|
15
|
+
when :welcome
|
16
|
+
"Welcome To Mastermind"
|
17
|
+
when :prompt
|
18
|
+
"Please Enter the Code: "
|
19
|
+
when :guess
|
20
|
+
"#{game_result.guess}"
|
21
|
+
when :win
|
22
|
+
if(game_result.num_of_tries == 1)
|
23
|
+
"Solved in #{game_result.num_of_tries} try!"
|
24
|
+
else
|
25
|
+
"Solved in #{game_result.num_of_tries} tries!"
|
26
|
+
end
|
27
|
+
when :lose
|
28
|
+
"Game over. Unable to solve in 10 turns."
|
29
|
+
when :color_scheme
|
30
|
+
"Enter a 6 letter color scheme or press Enter to use default"
|
31
|
+
else
|
32
|
+
"Come again?"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Mastermind
|
2
|
+
class CodeGenerator
|
3
|
+
def initialize(colors, code_length)
|
4
|
+
@colors = colors
|
5
|
+
@code_length = code_length
|
6
|
+
@terminal = Terminal.new
|
7
|
+
@game_text = GameText.new
|
8
|
+
end
|
9
|
+
|
10
|
+
def get_valid_code
|
11
|
+
input = get_input
|
12
|
+
unless Validator.new(input, @code_length, @colors ).valid?
|
13
|
+
get_valid_code
|
14
|
+
else
|
15
|
+
input
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def get_input
|
20
|
+
@terminal.display(@game_text.message(:prompt) )
|
21
|
+
@terminal.formatted_input
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,256 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
require_relative '../lib/mastermind'
|
3
|
+
require_relative '../lib/mastermind/AIsolver'
|
4
|
+
require_relative '../lib/mastermind/GameRules'
|
5
|
+
require_relative '../lib/mastermind/GameStatus'
|
6
|
+
require_relative '../lib/mastermind/TerminalInterface'
|
7
|
+
|
8
|
+
include Mastermind
|
9
|
+
|
10
|
+
DEFAULT_COLORS = %w{R G O Y B P}
|
11
|
+
|
12
|
+
describe 'Mastermind' do
|
13
|
+
WIN_HASH = {correct_positions: 4, correct_colors: 0}
|
14
|
+
|
15
|
+
let(:code){ %w{R R R R} }
|
16
|
+
let (:default_colors){ %w{R G O Y B P} }
|
17
|
+
|
18
|
+
describe 'GameStatus' do
|
19
|
+
let (:code){ %w{A B C D} }
|
20
|
+
let (:incorrect_guess){ %w{A C B E} }
|
21
|
+
let (:board){GameStatus.new(code, DEFAULT_COLORS)}
|
22
|
+
|
23
|
+
it 'stores the valid letters' do
|
24
|
+
expect(board.valid_letters).to eq(default_colors)
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'returns a CurrentResult after tries a guess'
|
28
|
+
|
29
|
+
it 'returns an incorrect result when incorrect guess' do
|
30
|
+
expect(board.process_guess(incorrect_guess).correct?).to eq(false)
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'returns a correct result when correct guess (win)' do
|
34
|
+
expect(board.process_guess(code).correct?).to eq(true)
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'detects the end of game on a win' do
|
38
|
+
result = CurrentResult.new(code, nil, nil)
|
39
|
+
expect(board.end_of_game?(result)).to eq(true)
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'detects the end of game on a loss' do
|
43
|
+
result = CurrentResult.new(nil, 10, nil)
|
44
|
+
expect(board.end_of_game?(result)).to eq(true)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe 'CurrentResult' do
|
49
|
+
it 'returns correct when winning result hash' do
|
50
|
+
correct_hash = {correct_positions: 4 , correct_colors:0}
|
51
|
+
expect(CurrentResult.new(nil, nil, correct_hash).correct?).to eq(true)
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'returns incorrect when incorrect guess' do
|
55
|
+
incorrect_hash = {correct_positions: 1 , correct_colors:0}
|
56
|
+
expect(CurrentResult.new(nil, nil, incorrect_hash).correct?).to eq(false)
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'stores the hash, num_of_tries and guess'
|
60
|
+
end
|
61
|
+
|
62
|
+
describe 'CodeComparer' do
|
63
|
+
let (:code){ %w{A B C D} }
|
64
|
+
let (:incorrect_guess){ %w{A C B E} }
|
65
|
+
let (:code_comparer){CodeComparer.new(code,incorrect_guess)}
|
66
|
+
|
67
|
+
it 'returns a hash with number of positions/colors' do
|
68
|
+
result_hash = {correct_positions: 1, correct_colors:2}
|
69
|
+
expect(code_comparer.compare).to eq(result_hash)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe 'Colors' do
|
74
|
+
let(:default_colors){%w{R G O Y B P}}
|
75
|
+
it 'returns default colors if incorrect size of input array' do
|
76
|
+
custom_colors = %w{Q Z F R}
|
77
|
+
expect(Colors.new(custom_colors).valid_colors).to match_array(default_colors)
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'returns default colors if no arguments' do
|
81
|
+
expect(Colors.new.valid_colors).to match_array(default_colors)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
describe 'NaiveAlgorithm' do
|
86
|
+
let (:naive_algorithm){NaiveAlgorithm.new(default_colors)}
|
87
|
+
before(:all) do
|
88
|
+
result_hash = {correct_positions: 0, correct_colors: 0}
|
89
|
+
guess = %w{R R R R}
|
90
|
+
@incorrect_guess = CurrentResult.new(guess, nil, result_hash )
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'initializes possible guesses to all permutations' do
|
94
|
+
expect(naive_algorithm.possible_guesses.size).to eq(1296)
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'chooses a valid next_guess' do
|
98
|
+
expect(naive_algorithm.next_guess).to be
|
99
|
+
end
|
100
|
+
|
101
|
+
it 'randomizes the next guess' do
|
102
|
+
first_guess = naive_algorithm.next_guess
|
103
|
+
second_guess = naive_algorithm.next_guess
|
104
|
+
expect(first_guess).not_to eq(second_guess)
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'discards invalid guesses based on previous result' do
|
108
|
+
expect(naive_algorithm.discard_invalid_guesses(@incorrect_guess)).not_to include( %w{R R R R} )
|
109
|
+
end
|
110
|
+
|
111
|
+
it 'keeps guesses that are still valid' do
|
112
|
+
expect(naive_algorithm.discard_invalid_guesses(@incorrect_guess)).to include( %w{G G G G} )
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
describe 'AIPlayer' do
|
117
|
+
let(:algorithm){NaiveAlgorithm.new(DEFAULT_COLORS)}
|
118
|
+
let(:board){GameStatus.new(code, DEFAULT_COLORS)}
|
119
|
+
let(:ai_player){AIPlayer.new(board, algorithm)}
|
120
|
+
let(:solution){CurrentResult.new(code, 1, WIN_HASH )}
|
121
|
+
|
122
|
+
|
123
|
+
it 'calls process_guess once if wins on first try' do
|
124
|
+
allow(algorithm).to receive(:next_guess){ code }
|
125
|
+
expect(board).to receive(:process_guess).with(code).and_return(solution)
|
126
|
+
ai_player.solve
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
describe 'GameText' do
|
131
|
+
let(:game_text){GameText.new}
|
132
|
+
|
133
|
+
it 'displays welcome message' do
|
134
|
+
expect(game_text.message(:welcome)).to eq("Welcome To Mastermind")
|
135
|
+
end
|
136
|
+
|
137
|
+
it 'prompts user for input' do
|
138
|
+
expect(game_text.message(:prompt)).to eq("Please Enter the Code: ")
|
139
|
+
end
|
140
|
+
|
141
|
+
it 'displays winning message' do
|
142
|
+
code = %w{R R R R}
|
143
|
+
result = CurrentResult.new(code, 1, WIN_HASH)
|
144
|
+
expect(game_text.message(:win, result)).to eq("Solved in 1 try!")
|
145
|
+
end
|
146
|
+
|
147
|
+
it 'pluralizes winning message' do
|
148
|
+
code = %w{R R R R}
|
149
|
+
result = CurrentResult.new(code, 2, WIN_HASH)
|
150
|
+
expect(game_text.message(:win, result)).to eq("Solved in 2 tries!")
|
151
|
+
end
|
152
|
+
|
153
|
+
it 'displays losing message' do
|
154
|
+
expect(game_text.message(:lose)).to eq("Game over. Unable to solve in 10 turns.")
|
155
|
+
end
|
156
|
+
|
157
|
+
it 'prompts user for color scheme' do
|
158
|
+
expect(game_text.message(:color_scheme)).to eq("Enter a 6 letter color scheme or press Enter to use default")
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
|
163
|
+
describe 'Game' do
|
164
|
+
let(:game_text){GameText.new}
|
165
|
+
let(:terminal_obj){double('terminal_obj') }
|
166
|
+
let(:game){ Game.new(game_text, terminal_obj) }
|
167
|
+
|
168
|
+
#
|
169
|
+
# it 'returns input when valid' do
|
170
|
+
# allow(Terminal).to receive(:new){terminal_obj}
|
171
|
+
# expect(terminal_obj).to receive(:formatted_input).once.ordered.and_return(%w{R R R R} )
|
172
|
+
# expect(terminal_obj).to receive(:display)
|
173
|
+
#
|
174
|
+
# result = game.get_input
|
175
|
+
# expect(Validator.new(result).valid?).to eq(true)
|
176
|
+
# end
|
177
|
+
#
|
178
|
+
# it 'calls the function until valid' do
|
179
|
+
# allow(Terminal).to receive(:new){terminal_obj}
|
180
|
+
# expect(terminal_obj).to receive(:formatted_input).once.ordered.and_return(%w{Z Z Z Z} )
|
181
|
+
# expect(terminal_obj).to receive(:formatted_input).once.ordered.and_return(%w{R R R R} )
|
182
|
+
# expect(terminal_obj).to receive(:display)
|
183
|
+
# expect(terminal_obj).to receive(:display)
|
184
|
+
#
|
185
|
+
# result = game.get_input
|
186
|
+
# expect(Validator.new(result).valid?).to eq(true)
|
187
|
+
# end
|
188
|
+
#
|
189
|
+
# it 'gets a Solution from winning AIPlayer' do
|
190
|
+
# game.set_up_board(%w{R R R R})
|
191
|
+
# expect(game.run_ai_player.correct?).to eq(true)
|
192
|
+
# end
|
193
|
+
# it 'prints winning end message if win' do
|
194
|
+
# code = %w{R R R R}
|
195
|
+
# result = CurrentResult.new(code, 1, WIN_HASH)
|
196
|
+
# expect{game.end_of_game(result)}.to output("You win!\n").to_stdout
|
197
|
+
# end
|
198
|
+
#
|
199
|
+
# it 'prints losing end message if lose' do
|
200
|
+
# result = CurrentResult.new(nil, nil, nil)
|
201
|
+
# game.set_up_board(%w{R R R R})
|
202
|
+
# expect{game.end_of_game(result)}.to output("Haha! You lost!\n").to_stdout
|
203
|
+
# end
|
204
|
+
|
205
|
+
it 'runs through the game' do
|
206
|
+
allow(terminal_obj).to receive(:display){}
|
207
|
+
allow(game_text).to receive(:message)
|
208
|
+
expect(game).to receive(:get_input).and_return(%w{R O Y B} )
|
209
|
+
expect(game).to receive(:get_color_scheme).and_return(%w{ R G O Y B P})
|
210
|
+
game.play_game
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
describe 'Terminal' do
|
215
|
+
let(:terminal){Terminal.new}
|
216
|
+
|
217
|
+
it 'displays message' do
|
218
|
+
expect{terminal.display('test message')}.to output("test message\n").to_stdout
|
219
|
+
end
|
220
|
+
|
221
|
+
it 'returns array of input letters' do
|
222
|
+
uppercase_input = StringIO.new("ABCD\n")
|
223
|
+
expect(terminal.formatted_input(uppercase_input)).to eq( %w{A B C D} )
|
224
|
+
end
|
225
|
+
|
226
|
+
it 'converts input to uppercase' do
|
227
|
+
lowercase_input = StringIO.new("abcd\n")
|
228
|
+
expect(terminal.formatted_input(lowercase_input)).to eq(%w{A B C D})
|
229
|
+
end
|
230
|
+
|
231
|
+
it 'ignores whitespace' do
|
232
|
+
whitespace_input = StringIO.new("a b c d\n")
|
233
|
+
expect(terminal.formatted_input(whitespace_input)).to eq(%w{A B C D})
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
|
238
|
+
describe 'Validator' do
|
239
|
+
it 'accepts a correct code' do
|
240
|
+
correct_validator = Validator.new( %w{R G O Y}, 4, DEFAULT_COLORS)
|
241
|
+
expect(correct_validator.valid?).to eq(true)
|
242
|
+
end
|
243
|
+
|
244
|
+
it 'fails if code length is incorrect' do
|
245
|
+
wrong_length = Validator.new( %w{R R R R R R}, 4, DEFAULT_COLORS)
|
246
|
+
expect(wrong_length.valid?).to eq(false)
|
247
|
+
end
|
248
|
+
|
249
|
+
|
250
|
+
|
251
|
+
it 'fails if either letters or code length are incorrect' do
|
252
|
+
wrong_letters = Validator.new( %w{R G O Y}, 4, %w{Q W E R T Y})
|
253
|
+
expect(wrong_letters.valid?).to eq(false)
|
254
|
+
end
|
255
|
+
end
|
256
|
+
end
|
metadata
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: mastermind-cmdline
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Samantha Wojtowicz
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2014-06-25 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: Naive Mastermind AI
|
15
|
+
email:
|
16
|
+
executables:
|
17
|
+
- mastermind
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- lib/mastermind.rb
|
22
|
+
- lib/mastermind/TerminalInterface.rb
|
23
|
+
- lib/mastermind/GameStatus.rb
|
24
|
+
- lib/mastermind/AIsolver.rb
|
25
|
+
- lib/mastermind/UserInterface.rb
|
26
|
+
- lib/mastermind/GameRules.rb
|
27
|
+
- test/mastermind_spec.rb
|
28
|
+
- bin/mastermind
|
29
|
+
homepage:
|
30
|
+
licenses: []
|
31
|
+
post_install_message:
|
32
|
+
rdoc_options: []
|
33
|
+
require_paths:
|
34
|
+
- lib
|
35
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
36
|
+
none: false
|
37
|
+
requirements:
|
38
|
+
- - ! '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
42
|
+
none: false
|
43
|
+
requirements:
|
44
|
+
- - ! '>='
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '0'
|
47
|
+
requirements: []
|
48
|
+
rubyforge_project:
|
49
|
+
rubygems_version: 1.8.23
|
50
|
+
signing_key:
|
51
|
+
specification_version: 3
|
52
|
+
summary: mastermind-cmdline
|
53
|
+
test_files: []
|