Skip to content

Commit 4facb56

Browse files
committed
Merge pull request #206 from rpottsoh/updateBowling
2 parents 5c4c102 + 89d0592 commit 4facb56

File tree

2 files changed

+112
-9
lines changed

2 files changed

+112
-9
lines changed

exercises/bowling/uBowlingExample.pas

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ interface
55
type
66
IBowlingGame = interface(IInvokable)
77
['{D4A292B6-BC15-48ED-AE04-2D34759017CB}']
8-
procedure Roll(aPins: integer);
8+
function Roll(aPins: integer): Boolean;
99
function Score: integer;
1010
end;
1111

@@ -28,10 +28,11 @@ TBowlingGame = class(TInterfacedObject, IBowlingGame)
2828
function SpareBonus(aFrameIndex: integer): integer;
2929
function SumOfPinsInFrame(aFrameIndex: integer): integer;
3030
function CorrectNumberOfRolls(aFrameIndex: integer): boolean;
31+
function ValidInput(aPin: integer): Boolean;
3132
public
3233
constructor create;
3334
function Score: integer;
34-
procedure Roll(aPins: integer);
35+
function Roll(aPins: integer): Boolean;
3536
end;
3637

3738
function NewBowlingGame: IBowlingGame;
@@ -44,8 +45,11 @@ constructor TBowlingGame.create;
4445
fRolls := TList<integer>.Create;
4546
end;
4647

47-
procedure TBowlingGame.Roll(aPins: Integer);
48+
function TBowlingGame.Roll(aPins: Integer): Boolean;
4849
begin
50+
if not ValidInput(aPins) then
51+
exit(false);
52+
4953
fRolls.Add(aPins);
5054
end;
5155

@@ -59,6 +63,8 @@ function TBowlingGame.Score: integer;
5963
lScore := 0;
6064
lFrameIndex := 0;
6165
try
66+
if (fRolls.Count < 12) or (fRolls.Count > 21) then
67+
raise EArgumentException.Create('Not a proper game');
6268
for i := 1 to fNumberOfFrames do
6369
begin
6470
if fRolls.Count <= lFrameIndex then
@@ -70,7 +76,7 @@ function TBowlingGame.Score: integer;
7076
raise EArgumentException.Create('Not a proper game');
7177

7278
lStrikeBonus := StrikeBonus(lFrameIndex);
73-
if (lStrikeBonus > fMaximumFrameScore) and not IsStrike(lFrameIndex + 1) then
79+
if (lStrikeBonus > fMaximumFrameScore) and not IsStrike(lFrameIndex + 1) or (lStrikeBonus > 20) then
7480
raise EArgumentException.Create('Not a proper game');
7581

7682
lScore := lScore + 10 + lStrikeBonus;
@@ -126,6 +132,27 @@ function TBowlingGame.SumOfPinsInFrame(aFrameIndex: Integer): integer;
126132
result := fRolls[aFrameIndex] + fRolls[aFrameIndex + 1];
127133
end;
128134

135+
function TBowlingGame.ValidInput(aPin: integer): Boolean;
136+
begin
137+
result := true;
138+
if (fRolls.Count >= 21) or (aPin < 0) or (aPin > 10) or
139+
((fRolls.Count + 1) mod 2 = 0) and (fRolls[fRolls.Count - 1] <> 10) and ((fRolls[fRolls.Count - 1] + aPin) > 10) then
140+
exit(false);
141+
142+
if (fRolls.Count = 20) then
143+
begin
144+
if (fRolls[18] <> 10) and (fRolls[18] + fRolls[19] <> 10) then
145+
exit(false);
146+
147+
if (aPin = 10) and ((fRolls[18] <> 10) or (fRolls[19] <> 10) or (fRolls[19] + aPin > 10) and (fRolls[19] + aPin <> 20)) and
148+
(fRolls[18] + fRolls[19] <> 10) then
149+
exit(false);
150+
151+
if (aPin <> 10) and (fRolls[19] + aPin > 10) and (fRolls[19] <> 10) then
152+
exit(false);
153+
end;
154+
end;
155+
129156
function TBowlingGame.CorrectNumberOfRolls(aFrameIndex: Integer): boolean;
130157
begin
131158
result := aFrameIndex = fRolls.Count;

exercises/bowling/uBowlingTests.pas

Lines changed: 81 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ interface
55
DUnitX.TestFramework,
66
uBowling;
77

8+
const
9+
CanonicalVersion = '1.2.0';
10+
811
type
912

1013
[TestFixture]
@@ -13,7 +16,7 @@ BowlingTests = class(TObject)
1316
class function RollMany(pins: array of integer; game: IBowlingGame): IBowlingGame; static;
1417
public
1518
[Test]
16-
// [Ignore('Comment the "[Ignore]" statement to run the test')]
19+
// [Ignore('Comment the "[Ignore]" statement to run the test')]
1720
procedure Should_be_able_to_score_a_game_with_all_zeros;
1821

1922
[Test]
@@ -80,10 +83,26 @@ BowlingTests = class(TObject)
8083
[Ignore]
8184
procedure Two_rolls_in_a_frame_cannot_score_more_than_10_points;
8285

86+
[Test]
87+
[Ignore]
88+
procedure Bonus_roll_after_a_strike_in_the_last_frame_cannot_score_more_than_10_points;
89+
8390
[Test]
8491
[Ignore]
8592
procedure Two_bonus_rolls_after_a_strike_in_the_last_frame_cannot_score_more_than_10_points;
8693

94+
[Test]
95+
[Ignore]
96+
procedure Two_bonus_rolls_after_a_strike_in_the_last_frame_can_score_more_than_10_points_if_one_is_a_strike;
97+
98+
[Test]
99+
[Ignore]
100+
procedure The_second_bonus_rolls_after_a_strike_in_the_last_frame_cannot_be_a_strike_if_the_first_one_is_not_a_strike;
101+
102+
[Test]
103+
[Ignore]
104+
procedure Second_bonus_roll_after_a_strike_in_the_last_frame_cannot_score_more_than_10_points;
105+
87106
[Test]
88107
[Ignore]
89108
procedure An_unstarted_game_cannot_be_scored;
@@ -94,7 +113,7 @@ BowlingTests = class(TObject)
94113

95114
[Test]
96115
[Ignore]
97-
procedure A_game_with_more_than_ten_frames_cannot_be_scored;
116+
procedure Cannot_roll_if_game_already_has_ten_frames;
98117

99118
[Test]
100119
[Ignore]
@@ -107,11 +126,26 @@ BowlingTests = class(TObject)
107126
[Test]
108127
[Ignore]
109128
procedure Bonus_roll_for_a_spare_in_the_last_frame_must_be_rolled_before_score_can_be_calculated;
129+
130+
[Test]
131+
[Ignore]
132+
procedure Cannot_roll_after_bonus_roll_for_spare;
133+
134+
[Test]
135+
[Ignore]
136+
procedure Cannot_roll_after_bonus_rolls_for_strike;
110137
end;
111138

112139
implementation
113140
uses System.SysUtils;
114141

142+
procedure BowlingTests.Second_bonus_roll_after_a_strike_in_the_last_frame_cannot_score_more_than_10_points;
143+
var game: IBowlingGame;
144+
begin
145+
game := RollMany([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10], NewBowlingGame);
146+
Assert.IsFalse(game.Roll(11));
147+
end;
148+
115149
procedure BowlingTests.Should_be_able_to_score_a_game_with_all_zeros;
116150
var game: IBowlingGame;
117151
begin
@@ -231,13 +265,27 @@ procedure BowlingTests.Two_rolls_in_a_frame_cannot_score_more_than_10_points;
231265
Assert.AreEqual(-1, game.Score);
232266
end;
233267

268+
procedure BowlingTests.The_second_bonus_rolls_after_a_strike_in_the_last_frame_cannot_be_a_strike_if_the_first_one_is_not_a_strike;
269+
var game: IBowlingGame;
270+
begin
271+
game := RollMany([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 6], NewBowlingGame);
272+
Assert.IsFalse(game.Roll(10));
273+
end;
274+
234275
procedure BowlingTests.Two_bonus_rolls_after_a_strike_in_the_last_frame_cannot_score_more_than_10_points;
235276
var game: IBowlingGame;
236277
begin
237278
game := RollMany([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 5, 6], NewBowlingGame);
238279
Assert.AreEqual(-1, game.Score);
239280
end;
240281

282+
procedure BowlingTests.Two_bonus_rolls_after_a_strike_in_the_last_frame_can_score_more_than_10_points_if_one_is_a_strike;
283+
var game: IBowlingGame;
284+
begin
285+
game := RollMany([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 10, 6], NewBowlingGame);
286+
Assert.AreEqual(26, game.Score);
287+
end;
288+
241289
procedure BowlingTests.An_unstarted_game_cannot_be_scored;
242290
var game: IBowlingGame;
243291
begin
@@ -252,11 +300,25 @@ procedure BowlingTests.An_incomplete_game_cannot_be_scored;
252300
Assert.AreEqual(-1, game.Score);
253301
end;
254302

255-
procedure BowlingTests.A_game_with_more_than_ten_frames_cannot_be_scored;
303+
procedure BowlingTests.Cannot_roll_after_bonus_rolls_for_strike;
256304
var game: IBowlingGame;
257305
begin
258-
game := RollMany([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], NewBowlingGame);
259-
Assert.AreEqual(-1, game.Score);
306+
game := RollMany([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 3, 2], NewBowlingGame);
307+
Assert.IsFalse(game.Roll(2));
308+
end;
309+
310+
procedure BowlingTests.Cannot_roll_after_bonus_roll_for_spare;
311+
var game: IBowlingGame;
312+
begin
313+
game := RollMany([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 3, 2], NewBowlingGame);
314+
Assert.IsFalse(game.Roll(2));
315+
end;
316+
317+
procedure BowlingTests.Cannot_roll_if_game_already_has_ten_frames;
318+
var game: IBowlingGame;
319+
begin
320+
game := RollMany([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], NewBowlingGame);
321+
Assert.IsFalse(game.Roll(0));
260322
end;
261323

262324
procedure BowlingTests.Bonus_rolls_for_a_strike_in_the_last_frame_must_be_rolled_before_score_can_be_calculated;
@@ -273,6 +335,20 @@ procedure BowlingTests.Both_bonus_rolls_for_a_strike_in_the_last_frame_must_be_r
273335
Assert.AreEqual(-1, game.Score);
274336
end;
275337

338+
procedure BowlingTests.Bonus_roll_after_a_strike_in_the_last_frame_cannot_score_more_than_10_points;
339+
var game: IBowlingGame;
340+
begin
341+
game := RollMany([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10], NewBowlingGame);
342+
Assert.IsFalse(game.Roll(11));
343+
(*{
344+
var sut = new BowlingGame();
345+
var previousRolls = new int[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10};
346+
DoRoll(previousRolls, sut);
347+
Assert.Throws<ArgumentException>(() => sut.Roll(11));
348+
} (**)
349+
350+
end;
351+
276352
procedure BowlingTests.Bonus_roll_for_a_spare_in_the_last_frame_must_be_rolled_before_score_can_be_calculated;
277353
var game: IBowlingGame;
278354
begin

0 commit comments

Comments
 (0)