Professional Documents
Culture Documents
0
(With Visual Studio 2010)
By Dan Stewart
dan@stewshack.com
SCORING BOWLING.
A spare is when the player knocks down all 10 pins in two tries. The
bonus for that frame is the number of pins knocked down by the next roll.
So in frame 3 above, the score is 10 (the total number knocked down)
plus a bonus of 5 (the number of pins knocked down on the next roll.)
A strike is when the player knocks down all 10 pins on his first try. The
bonus for that frame is the value of the next two balls rolled.
In the tenth frame a player who rolls a spare or strike is allowed to roll
the extra balls to complete the frame. However no more than three balls
can be rolled in tenth frame.
A QUICK DESIGN SESSION
Game
+ roll(pins : int) Clearly we need the Game class.
+ score() : int
A QUICK DESIGN SESSION
Game 10 Frame
+ roll(pins : int)
+ score() : int
Tenth Frame
1
The score function must
include all the frames,
and calculate all their scores. Tenth Frame
A QUICK DESIGN SESSION
The score for a spare or a strike
depends on the frame’s successor
Next frame
Tenth Frame
BEGIN.
Create a console application named BowlingGame
Add a MSTest project named BowlingGameTest to
the solution
BEGIN.
Add a unit test named GameTest to the project
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace BowlingGameTest
{
[TestClass]
public class GameTest
{
private TestContext testContextInstance;
public TestContext TestContext
{
get { return testContextInstance; }
set { testContextInstance = value; }
}
[TestMethod]
public void TestMethod1()
{
}
}
}
THE FIRST TEST.
[TestMethod]
public void TestGutterGame()
{
Game g = new Game();
}
THE FIRST TEST.
[TestMethod] namespace BowlingGame
public void TestGutterGame() {
{ public class Game
Game g = new Game(); {
} }
}
THE FIRST TEST.
[TestMethod] public class Game
public void TestGutterGame() {
{ }
Game g = new Game();
}
THE FIRST TEST.
[TestMethod] public class Game
public void TestGutterGame() {
{ }
Game g = new Game();
Assert.AreEqual(0, g.Score());
}
THE FIRST TEST.
[TestMethod] public class Game
public void TestGutterGame() {
{ public void Roll(int p)
Game g = new Game(); {
throw new System.NotImplementedException();
}
for (int i = 0; i < 20; i++)
{ public object Score()
g.Roll(0); {
} throw new System.NotImplementedException();
}
Assert.AreEqual(0, g.Score()); }
}
Assert.AreEqual(0, g.Score());
}
[TestMethod]
public void TestAllOnes()
{
for (int i = 0; i < 20; i++)
{
g.Roll(1);
}
Assert.AreEqual(20, g.Score());
}
- roll loop is duplicated
THE SECOND TEST.
[TestMethod] public class Game
public void TestGutterGame() {
{ private int score;
int rolls = 20;
int pins = 0; public void Roll(int pins)
{
for (int i = 0; i < rolls; i++) score += pins;
{ }
g.Roll(pins);
} public int Score()
{
Assert.AreEqual(0, g.Score()); return score;
} }
}
- roll loop is duplicated
THE SECOND TEST.
[TestMethod] public class Game
public void TestGutterGame() {
{ private int score;
int rolls = 20;
int pins = 0; public void Roll(int pins)
{
RollMany(rolls, pins); score += pins;
}
for (int i = 0; i < rolls; i++)
{ public int Score()
g.Roll(pins); {
} return score;
}
Assert.AreEqual(0, g.Score()); }
}
THE SECOND TEST.
public class Game
[TestMethod]
{
public void TestGutterGame()
private int score;
{
RollMany(20, 0);
public void Roll(int pins)
{
Assert.AreEqual(0, g.Score());
score += pins;
}
}
private void RollMany(int rolls, int pins)
public int Score()
{
{
for (int i = 0; i < rolls; i++)
return score;
{
}
g.Roll(pins);
}
}
}
THE SECOND TEST.
[TestMethod] public class Game
public void TestGutterGame() {
{ private int score;
RollMany(20, 0);
public void Roll(int pins)
Assert.AreEqual(0, g.Score()); {
} score += pins;
}
[TestMethod]
public void TestAllOnes() public int Score()
{ {
RollMany(20, 1); return score;
}
Assert.AreEqual(20, g.Score()); }
}
Design is wrong.
Responsibilities are
misplaced.
return score;
}
}
- ugly comment in test.
THE THIRD TEST.
[TestMethod] public class Game
public void TestOneSpare() {
{ private int[] rolls = new int[21];
g.Roll(5); private int currentRoll;
g.Roll(5); // spare
g.Roll(3); public void Roll(int pins)
RollMany(17, 0); {
rolls[currentRoll++] = pins;
Assert.AreEqual(16, g.Score()); }
}
public int Score()
{
int score = 0;
return score;
}
}
score += rolls[i];
}
return score;
}
return score;
}
}
- ugly comment in test.
THE THIRD TEST.
[TestMethod] public int Score()
public void TestOneSpare() {
{ int score = 0;
g.Roll(5); int roll = 0;
g.Roll(5); // spare
for (int frame = 0; frame < 10; frame++)
g.Roll(3);
{
RollMany(17, 0); score += rolls[roll] + rolls[roll + 1];
//Assert.AreEqual(16, g.Score()); roll += 2;
Assert.Inconclusive(); }
}
return score;
}
- ugly comment in test.
THE THIRD TEST.
[TestMethod] public int Score()
public void TestOneSpare() {
{ int score = 0;
g.Roll(5); int roll = 0;
g.Roll(5); // spare
for (int frame = 0; frame < 10; frame++)
g.Roll(3);
{
RollMany(17, 0); score += rolls[roll] + rolls[roll + 1];
roll += 2;
Assert.AreEqual(16, g.Score()); }
}
return score;
}
roll += 2;
}
return score;
}
-ugly comment in test.
-ugly comment in conditional.
THE THIRD TEST.
[TestMethod] public int Score()
public void TestOneSpare() {
{ int score = 0;
int roll = 0;
g.Roll(5);
g.Roll(5); // spare for (int frame = 0; frame < 10; frame++)
g.Roll(3); {
RollMany(17, 0); // spare
if (rolls[roll] + rolls[roll + 1] == 10)
Assert.AreEqual(16, g.Score()); {
} score += 10 + rolls[roll + 2];
}
else
{
score += rolls[roll] + rolls[roll + 1];
}
roll += 2;
}
return score;
}
- ugly comment in test.
THE THIRD TEST.
[TestMethod] public int Score()
public void TestOneSpare() {
{ int score = 0;
int roll = 0;
g.Roll(5);
g.Roll(5); // spare for (int frame = 0; frame < 10; frame++)
g.Roll(3); {
RollMany(17, 0); if (IsSpare(roll))
{
Assert.AreEqual(16, g.Score()); score += 10 + rolls[roll + 2];
} }
else
{
score += rolls[roll] + rolls[roll + 1];
}
roll += 2;
}
return score;
}
return score;
}
roll += 2;
}
return score;
}
return score;
}
-ugly comment in
testOneStrike.
-ugly comment in conditional.
THE FOURTH TEST.
[TestMethod] public int Score()
{
public void TestOneStrike() int score = 0;
{ int roll = 0;
g.Roll(10); // strike
for (int frame = 0; frame < 10; frame++)
g.Roll(3); {
g.Roll(4); if (rolls[roll] == 10) // strike
RollMany(16, 0); {
score += 10 + StrikeBonus(roll);
Assert.AreEqual(24, g.Score()); roll++;
} }
else if (IsSpare(roll))
{
score += 10 + SpareBonus(roll);
roll += 2;
}
else
{
score += SumOfBallsInFrame(roll);
roll += 2;
}
}
return score;
}
roll++;
}
else if (IsSpare(roll))
{
score += 10
+ SpareBonus(roll);
roll += 2;
}
else
{
score += SumOfBallsInFrame(roll);
roll += 2;
}
}
return score;
}
}
else
{
score += SumOfBallsInFrame(roll);
roll += 2;
}
}
return score;
}
THE FIFTH TEST.
[TestMethod] public int Score()
public void TestPerfectGame() {
{ int score = 0;
RollMany(12, 10); int roll = 0;
roll++;
}
else if (IsSpare(roll))
{
score += 10
+ SpareBonus(roll);
roll += 2;
}
else
{
score += SumOfBallsInFrame(roll);
roll += 2;
}
}
return score;
}
QUESTIONS?