Skip to content

Commit eb01d18

Browse files
authored
Merge pull request #98 from rlmoser99/remove_recursion
Remove recursive methods
2 parents d70b4c9 + ae51046 commit eb01d18

9 files changed

+330
-260
lines changed

lib/13_input_output.rb

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -57,20 +57,26 @@ def initialize(solution = rand(0..9), guess = nil, count = 0)
5757

5858
def play_game
5959
puts "Let's play a game called 'Guess a random number!'"
60-
player_turn until game_over?
60+
turn_order until game_over?
6161
final_message
6262
end
6363

64-
def player_turn
65-
@guess = verify_input(player_input)
64+
def turn_order
65+
player_turn
6666
@count += 1
6767
end
6868

69+
def player_turn
70+
loop do
71+
@guess = verify_input(player_input)
72+
break if @guess
73+
74+
puts 'Input error!'
75+
end
76+
end
77+
6978
def verify_input(number)
7079
return number if number.match?(/^[0-9]$/)
71-
72-
puts 'Input error!'
73-
verify_input(player_input)
7480
end
7581

7682
def game_over?

lib/15_binary_main.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,5 @@
88

99
minimum = 1
1010
maximum = 100
11-
@game = BinaryGame.new(minimum, maximum)
12-
@game.play_game
11+
game = BinaryGame.new(minimum, maximum)
12+
game.play_game

lib/15a_binary_game.rb

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,17 @@ def play_game
2323
end
2424

2525
def player_input(min, max)
26-
number = gets.chomp.to_i
27-
return number if number.between?(min, max)
26+
loop do
27+
user_input = gets.chomp
28+
verified_number = verify_input(min, max, user_input.to_i) if user_input.match?(/^\d+$/)
29+
return verified_number if verified_number
2830

29-
puts "Input error! Please enter a number between #{min} or #{max}."
30-
player_input(min, max)
31+
puts "Input error! Please enter a number between #{min} or #{max}."
32+
end
33+
end
34+
35+
def verify_input(min, max, input)
36+
return input if input.between?(min, max)
3137
end
3238

3339
def update_random_number

spec/13_input_output_spec.rb

Lines changed: 63 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,10 @@
4444
end
4545

4646
# ASSIGNMENT #1
47+
4748
# Write a similar test to the one above, that uses a custom matcher
4849
# instead of <, >, =.
4950
matcher :be_between_zero_and_nine do
50-
match { |number| number.between?(0, 9) }
5151
end
5252

5353
# remove the 'x' before running this test
@@ -68,6 +68,7 @@
6868
end
6969

7070
# ASSIGNMENT #2
71+
7172
# Create a new instance of NumberGame and write a test for when the @guess
7273
# does not equal @solution.
7374
context 'when user guess is not correct' do
@@ -80,93 +81,89 @@
8081
# The #player_input method is used in the game as an argument passed into the
8182
# verify_input method. The #player_input method is not tested because it is a
8283
# private method. In addition, it is unnecessary to test methods that only
83-
# contain puts and/or gets. However, at the bottom of the answer file is an
84-
# example of how you would test the #player_input method if it were not
85-
# private.
84+
# contain puts and/or gets.
8685

8786
# Since we do not have to test #player_input, let's test #verify_input.
8887

8988
describe '#verify_input' do
90-
# Note: #verify_input is a recursive method that will repeat until
91-
# number.match?(/^[0-9]$/) is true.
89+
subject(:verify_game) { described_class.new }
90+
# Note: #verify_input will only return a value if it matches /^[0-9]$/
9291

9392
context 'when given a valid input as argument' do
9493
it 'returns valid input' do
9594
user_input = '3'
96-
verified_input = game.verify_input(user_input)
95+
verified_input = verify_game.verify_input(user_input)
9796
expect(verified_input).to eq('3')
9897
end
9998
end
10099

101-
# In order to test #verify_input receiving an invalid input, we need to use
102-
# a method stub. In this example, the method stub will return the valid
103-
# input, 'number_input', which will be the final result of this test.
104-
# To stub this method, you 'allow' the test subject (game) to receive the
105-
# :method_name and to return a specific value.
100+
# ASSIGNMENT #3
101+
102+
# Write a test for the following context.
103+
context 'when given invalid input as argument' do
104+
xit 'returns nil' do
105+
end
106+
end
107+
end
108+
109+
describe '#player_turn' do
110+
# In order to test the behavior of #player_turn, we need to use a method
111+
# stub for #player_input to return a valid_input ('3'). To stub a method,
112+
# we 'allow' the test subject (player_game) to receive the :method_name
113+
# and to return a specific value.
106114
# https://relishapp.com/rspec/rspec-mocks/v/2-14/docs/method-stubs/allow-with-a-simple-return-value
107115
# http://testing-for-beginners.rubymonstas.org/test_doubles.html
108116

109-
context 'when given invalid input once before valid input' do
110-
letter_input = 'g'
111-
number_input = '5'
117+
subject(:player_game) { described_class.new }
112118

113-
# When using the same 'Arrange' part of a test, you can utilize before
114-
# hooks to set up the test conditions.
115-
# https://relishapp.com/rspec/rspec-core/v/2-0/docs/hooks/before-and-after-hooks\
119+
context 'when user input is valid' do
120+
# To test the behavior, we want to test that the loop stops before the
121+
# puts 'Input error!' line. In order to test that this method is not
122+
# called, we use a message expectation.
123+
# https://relishapp.com/rspec/rspec-mocks/docs
116124

117-
before do
118-
# The stub below will return the number_input when called.
119-
allow(game).to receive(:player_input).and_return(number_input)
125+
it 'stops loop and does not display error message' do
126+
valid_input = '3'
127+
allow(player_game).to receive(:player_input).and_return(valid_input)
128+
# To use a message expectation, move 'Assert' before 'Act'.
129+
expect(player_game).not_to receive(:puts).with('Input error!')
130+
player_game.player_turn
120131
end
132+
end
121133

122-
it 'loops once until it receives valid input' do
123-
# The stub below will remove the 'Input error!' from appearing in the
124-
# test output.
125-
allow(game).to receive(:puts)
126-
127-
# This test starts with the invalid parameter (letter_input = 'g').
128-
verified_input = game.verify_input(letter_input)
134+
context 'when user inputs an incorrect value once, then a valid input' do
135+
# A method stub can be called multiple times and return different values.
136+
# https://relishapp.com/rspec/rspec-mocks/docs/configuring-responses/returning-a-value
137+
# Create a stub method to receive :player_input and return the invalid
138+
# 'letter' input, then the 'valid_input'
129139

130-
# The result of 'verified_input' is the valid parameter, because
131-
# of the player_input stub in the before hook (number_input = '5').
132-
expect(verified_input).to eq('5')
140+
# As the 'Arrange' step for tests grows, you can use a before hook to
141+
# separate the test from the set-up.
142+
# https://relishapp.com/rspec/rspec-core/v/2-0/docs/hooks/before-and-after-hooks\
143+
# https://www.tutorialspoint.com/rspec/rspec_hooks.htm
144+
before do
145+
letter = 'd'
146+
valid_input = '8'
147+
allow(player_game).to receive(:player_input).and_return(letter, valid_input)
133148
end
134149

135-
it 'displays error message once' do
136-
# Due to the loop, we can test that the game received :puts with the
137-
# error message one time. In order to test if this method is called,
138-
# we use a message expectation.
139-
# https://relishapp.com/rspec/rspec-mocks/docs
140-
141-
# To set a message expectation, move 'Assert' before 'Act'.
142-
expect(game).to receive(:puts).once.with('Input error!')
143-
game.verify_input(letter_input)
150+
# When using message expectations, you can specify how many times you
151+
# expect the message to be received.
152+
# https://relishapp.com/rspec/rspec-mocks/docs/setting-constraints/receive-counts
153+
it 'completes loop and displays error message once' do
154+
expect(player_game).to receive(:puts).with('Input error!').once
155+
player_game.player_turn
144156
end
145157
end
146158

147-
# ASSIGNMENT #3
148-
context 'when given invalid input twice before valid input' do
149-
letter_input = 'h'
150-
number_input = '3'
151-
# Create another invalid input (anything except a digit between 0 and 9).
159+
# ASSIGNMENT #4
152160

161+
# Write a test for the following context.
162+
context 'when user inputs two incorrect values, then a valid input' do
153163
before do
154-
# A method stub can be called multiple times and return different values.
155-
# https://relishapp.com/rspec/rspec-mocks/docs/configuring-responses/returning-a-value
156-
# Create a stub method to receive :player_input and return your invalid
157-
# input and the number_input.
158-
end
159-
160-
# remove the 'x' before running this test
161-
xit 'loops twice until it receives valid input' do
162-
# Creating a stub method for :puts is optional
163-
164-
verified_input = game.verify_input(letter_input)
165-
expect(verified_input).to eq(number_input)
166164
end
167165

168-
# remove the 'x' before running this test
169-
xit 'displays error message twice' do
166+
xit 'completes loop and displays error message twice' do
170167
end
171168
end
172169
end
@@ -192,21 +189,21 @@
192189
end
193190
end
194191

195-
# ASSIGNMENT #4
196-
context 'when count is 2-3' do
197-
# Create a new instance of NumberGame, with specific values for @solution,
198-
# @guess, and @count.
192+
# ASSIGNMENT #5
199193

194+
# Create a new instance of NumberGame, with specific values for @solution,
195+
# @guess, and @count
196+
context 'when count is 2-3' do
200197
# remove the 'x' before running this test
201198
xit 'outputs correct phrase' do
202199
congrats_phrase = "Congratulations! You picked the random number in 3 guesses!\n"
203200
expect { game.final_message }.to output(congrats_phrase).to_stdout
204201
end
205202
end
206203

207-
# ASSIGNMENT #5
208-
# Create a new instance of NumberGame, with specific values for @solution,
209-
# @guess, and @count. Write a test for the following context.
204+
# ASSIGNMENT #6
205+
206+
# Write a test for the following context.
210207
context 'when count is 4 and over' do
211208
# remove the 'x' before running this test
212209
xit 'outputs correct phrase' do

0 commit comments

Comments
 (0)