SlideShare a Scribd company logo
1 of 49
Adapted for C# 4.0 (With Visual Studio 2010) By Dan Stewart dan@stewshack.com
Scoring Bowling. The game consists of 10 frames as shown above.  In each frame the player has two opportunities to knock down 10 pins.  The score for the frame is the total number of pins knocked down, plus bonuses for strikes and spares. 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 Clearly we need the Game class.
A quick design session A game has 10 frames.
A quick design session A frame has 1 or two rolls.
A quick design session The tenth frame has two or three rolls. It is different from all the other frames.
A quick design session The score function must include all the frames,  and calculate all their scores.
A quick design session The score for a spare or a strike depends on the frame’s successor
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] publicclassGameTest     { privateTestContext testContextInstance; publicTestContext TestContext         { get { return testContextInstance; } set { testContextInstance = value; }         }         [TestMethod] publicvoid TestMethod1()         {         }     } }
The first test. [TestMethod] publicvoidTestGutterGame()  {      Game g = new Game(); }
The first test. namespaceBowlingGame { publicclassGame     {     } } [TestMethod] publicvoidTestGutterGame() {      Game g = new Game(); }
The first test. [TestMethod] publicvoidTestGutterGame() {      Game g = new Game(); } publicclassGame { }
The first test. [TestMethod] publicvoidTestGutterGame() {     Gameg = newGame(); for(int i = 0; i < 20; i++)  {     g.Roll(0);  } } publicclassGame { }
The first test. public class Game {    publicvoid Roll(int p) {    thrownewSystem.NotImplementedException(); } } [TestMethod] publicvoidTestGutterGame() {     Gameg = newGame(); for(int i = 0; i < 20; i++)  {     g.Roll(0);  } }
The first test. [TestMethod] publicvoidTestGutterGame() {    Gameg = newGame(); for(int i = 0; i < 20; i++) { g.Roll(0); } Assert.AreEqual(0, g.Score()); } public class Game {    publicvoid Roll(int p) {    thrownewSystem.NotImplementedException();    } }
The first test. [TestMethod] publicvoid TestGutterGame() {    Gameg = newGame(); for(int i = 0; i < 20; i++) {    g.Roll(0); } Assert.AreEqual(0, g.Score()); } publicclassGame {    publicvoid Roll(int p)    { thrownew System.NotImplementedException();    } publicobject Score() { thrownew System.NotImplementedException();    } } Failed TestGutterGame threw exception
The first test. [TestMethod] publicvoid TestGutterGame() {     Gameg = newGame(); for(int i = 0; i < 20; i++)  {        g.Roll(0);    } Assert.AreEqual(0, g.Score); } publicclassGame { privateint score; publicvoid Roll(int pins)  {  } publicintScore()  { returnscore;  } }
The Second test. [TestMethod] publicvoid TestAllOnes() {     Gameg = newGame();     for(int i = 0; i < 20; i++)  {     g.Roll(1);  } Assert.AreEqual(20, g.Score()); } publicclassGame { privateint score; publicvoid Roll(int pins)  {  } publicintScore()  { returnscore;  } }
The Second test. - Game creation is duplicated - roll loop is duplicated [TestMethod] publicvoid TestAllOnes() {     Gameg = newGame();     for(int i = 0; i < 20; i++)  {     g.Roll(1);  } Assert.AreEqual(20, g.Score()); } publicclassGame { privateint score; publicvoid Roll(int pins)  {  } publicintScore()  { returnscore;  } }
The Second test. - Game creation is duplicated - roll loop is duplicated [TestMethod] publicvoid TestAllOnes() {     Gameg = newGame();     for(int i = 0; i < 20; i++)  {     g.Roll(1);  } Assert.AreEqual(20, g.Score()); } publicclassGame { privateint score; publicvoid Roll(int pins) { } publicintScore() { return score;    } } Assert.AreEqual failed. Expected:<20>. Actual:<0>.
The Second test. - roll loop is duplicated privateGame g; [TestInitialize] publicvoid Initialize()  {     g = newGame(); } [TestCleanup] publicvoid Cleanup() {     g = null; } [TestMethod] publicvoid TestGutterGame() { for(int i = 0; i < 20; i++)  {     g.Roll(0);  } Assert.AreEqual(0, g.Score()); } [TestMethod] publicvoid TestAllOnes() { for(int i = 0; i < 20; i++)  {     g.Roll(1);  } Assert.AreEqual(20, g.Score()); } publicclassGame { privateint score; publicvoid Roll(int pins) { score += pins; } publicint Score() { return score;     } }
The Second test. - roll loop is duplicated [TestMethod] publicvoid TestGutterGame() {    int rolls = 20; intpins = 0; for(int i = 0; i < rolls; i++) {    g.Roll(pins); } Assert.AreEqual(0, g.Score()); } publicclassGame { privateint score; publicvoid Roll(int pins) { score += pins; } publicint Score() { return score;     } }
The Second test. - roll loop is duplicated [TestMethod] publicvoid TestGutterGame() {     int rolls = 20; intpins = 0;    RollMany(rolls, pins); for(int i = 0; i < rolls; i++)   {     g.Roll(pins);  } Assert.AreEqual(0, g.Score()); } publicclassGame { privateint score; publicvoid Roll(int pins) { score += pins; } publicint Score() { return score;     } }
The Second test. publicclassGame { privateint score; publicvoid Roll(int pins) { score += pins; } publicint Score() { return score;     } } [TestMethod] publicvoid TestGutterGame() {     RollMany(20, 0); Assert.AreEqual(0, g.Score()); } privatevoid RollMany(introlls, int pins) {     for(int i = 0; i < rolls; i++)  {     g.Roll(pins);  } }
The Second test. [TestMethod] publicvoid TestGutterGame() {     RollMany(20, 0); Assert.AreEqual(0, g.Score()); }         [TestMethod] publicvoid TestAllOnes() {     RollMany(20, 1); Assert.AreEqual(20, g.Score()); } privatevoid RollMany(int rolls, int pins) {     for(int i = 0; i < rolls; i++)  {     g.Roll(pins);  } } publicclassGame { privateint score; publicvoid Roll(int pins) { score += pins; } publicint Score() { return score;     } }
The Third test. - ugly comment in test. [TestMethod] publicvoid TestOneSpare() {     g.Roll(5);  g.Roll(5); // spare  g.Roll(3);  RollMany(17, 0); Assert.AreEqual(16, g.Score()); } publicclassGame { privateint score; publicvoid Roll(int pins) { score += pins; } publicint Score() { return score;     } } Failed Assert.AreEqual Expected:<16>. Actual:<13>
The Third test. - ugly comment in test. publicclassGame { privateint score; publicvoid Roll(int pins) { score += pins; } publicint Score() { return score;     } } [TestMethod] publicvoid TestOneSpare() {     g.Roll(5);  g.Roll(5); // spare  g.Roll(3);  RollMany(17, 0); Assert.AreEqual(16, g.Score()); } tempted to use flag to remember previous roll.  So design must be wrong. Failed Assert.AreEqual Expected:<16>. Actual:<13>
The Third test. - ugly comment in test. Roll() calculates score, but name does not imply that. publicclassGame { privateint score; publicvoid Roll(int pins) { score += pins; } publicint Score() { return score;     } } [TestMethod] publicvoid TestOneSpare() {     g.Roll(5);     g.Roll(5); // spare     g.Roll(3);     RollMany(17, 0); Assert.AreEqual(16, g.Score); } Score() does not calculate score, but name implies that it does. Design is wrong.  Responsibilities are misplaced. Failed Assert.AreEqual Expected:<16>. Actual:<13>
The Third test. - ugly comment in test. [TestMethod] publicvoid TestOneSpare() {     g.Roll(5);     g.Roll(5); // spare     g.Roll(3);     RollMany(17, 0); //Assert.AreEqual(16, g.Score()); Assert.Inconclusive(); } publicclassGame { privateint score; publicvoid Roll(int pins) { score += pins; } publicint Score() { return score;     } }
The Third test. - ugly comment in test. publicclassGame { privateint score; privateint[] rolls = newint[21]; privateint currentRoll; publicvoid Roll(int pins) { rolls[currentRoll++] = pins; score += pins; } publicint Score() { return score;     } } [TestMethod] publicvoid TestOneSpare() {     g.Roll(5);     g.Roll(5); // spare     g.Roll(3);     RollMany(17, 0); //Assert.AreEqual(16, g.Score()); Assert.Inconclusive(); }
The Third test. - ugly comment in test. publicclassGame {         privateint[] rolls = newint[21]; privateint currentRoll; publicvoid Roll(int pins) { rolls[currentRoll++] = pins; } publicint Score() { int score = 0; for (int i = 0; i < rolls.Length; i++) { score += rolls[i]; } return score;     } } [TestMethod] publicvoid TestOneSpare() {     g.Roll(5);  g.Roll(5); // spare  g.Roll(3);  RollMany(17, 0); //Assert.AreEqual(16, g.Score()); Assert.Inconclusive(); }
The Third test. - ugly comment in test. [TestMethod] publicvoid TestOneSpare() {     g.Roll(5);  g.Roll(5); // spare  g.Roll(3);  RollMany(17, 0); Assert.AreEqual(16, g.Score()); } publicclassGame {         privateint[] rolls = newint[21]; privateint currentRoll; publicvoid Roll(int pins) { rolls[currentRoll++] = pins; } publicint Score() { int score = 0; for (int i = 0; i < rolls.Length; i++) { score += rolls[i]; } return score;     } } Failed Assert.AreEqual Expected:<16>. Actual:<13>
The Third test. - ugly comment in test. publicint Score() { int score = 0; for (int i = 0; i < rolls.Length; i++)     {         // spare         if(rolls[i] + rolls[i+1] == 10) { score += ... } score += rolls[i]; } return score; } [TestMethod] publicvoid TestOneSpare() {     g.Roll(5);  g.Roll(5); // spare  g.Roll(3);  RollMany(17, 0); Assert.AreEqual(16, g.Score()); } This isn’t going to work because i might not refer to the first ball of the frame. Design is still wrong. Need to walk through array two balls (one frame) at a time. Failed Assert.AreEqual Expected:<16>. Actual:<13>
The Third test. - ugly comment in test. publicclassGame {         privateint[] rolls = newint[21]; privateint currentRoll; publicvoid Roll(int pins) { rolls[currentRoll++] = pins; } publicint Score() { int score = 0; for (int i = 0; i < rolls.Length; i++) { score += rolls[i]; } return score;     } } [TestMethod] publicvoid TestOneSpare() {     g.Roll(5);  g.Roll(5); // spare  g.Roll(3);  RollMany(17, 0); //Assert.AreEqual(16, g.Score()); Assert.Inconclusive(); }
The Third test. - ugly comment in test. publicint Score() { int score = 0; int roll = 0; for (int frame = 0; frame < 10; frame++) {         score += rolls[roll] + rolls[roll + 1]; roll += 2; } returnscore; } [TestMethod] publicvoid TestOneSpare() {     g.Roll(5);  g.Roll(5); // spare  g.Roll(3);  RollMany(17, 0); //Assert.AreEqual(16, g.Score()); Assert.Inconclusive(); }
The Third test. - ugly comment in test. [TestMethod] publicvoid TestOneSpare() {     g.Roll(5);  g.Roll(5); // spare  g.Roll(3);  RollMany(17, 0); Assert.AreEqual(16, g.Score()); } publicint Score() { int score = 0; int roll = 0; for (int frame = 0; frame < 10; frame++) {         score += rolls[roll] + rolls[roll + 1]; roll += 2; } returnscore; } Failed Assert.AreEqual Expected:<16>. Actual:<13>
The Third test. - ugly comment in test. publicint Score() { int score = 0; int roll = 0; for (int frame = 0; frame < 10; frame++) { // spare if (rolls[roll] + rolls[roll + 1] == 10) { score += 10 + rolls[roll + 2]; } else {             score += rolls[roll] + rolls[roll + 1];               } roll += 2; } return score; } [TestMethod] publicvoid TestOneSpare() {     g.Roll(5);  g.Roll(5); // spare  g.Roll(3);  RollMany(17, 0); Assert.AreEqual(16, g.Score()); }
The Third test. ,[object Object]
ugly comment in conditional.publicint Score() { int score = 0; int roll = 0; for (int frame = 0; frame < 10; frame++) { // spare if (rolls[roll] + rolls[roll + 1] == 10) { score += 10 + rolls[roll + 2]; } else {             score += rolls[roll] + rolls[roll + 1];               } roll += 2; } return score; } [TestMethod] publicvoid TestOneSpare() {     g.Roll(5);  g.Roll(5); // spare  g.Roll(3);  RollMany(17, 0); Assert.AreEqual(16, g.Score()); }
The Third test. - ugly comment in test. publicint Score() { int score = 0; int roll = 0; for (int frame = 0; frame < 10; frame++) {         if(IsSpare(roll)) {     score += 10 + rolls[roll + 2]; } else {             score += rolls[roll] + rolls[roll + 1]; } roll += 2; } returnscore; } privatebool IsSpare(int roll) {     returnrolls[roll] +     rolls[roll + 1] == 10; } [TestMethod] publicvoid TestOneSpare() {     g.Roll(5);  g.Roll(5); // spare  g.Roll(3);  RollMany(17, 0); Assert.AreEqual(16, g.Score()); }
The Third test. [TestMethod] publicvoid TestOneSpare() {     RollSpare(); g.Roll(3); RollMany(17, 0); Assert.AreEqual(16, g.Score()); } privatevoid RollSpare() {     g.Roll(5); g.Roll(5); } publicint Score() { int score = 0; int roll = 0; for (int frame = 0; frame < 10; frame++) {         if(IsSpare(roll)) {     score += 10 + rolls[roll + 2]; } else {             score += rolls[roll] + rolls[roll + 1]; } roll += 2; } returnscore; } privatebool IsSpare(int roll) {     returnrolls[roll] +     rolls[roll + 1] == 10; }
The Fourth test. - ugly comment in testOneStrike. [TestMethod] publicvoid TestOneStrike() {     g.Roll(10); // strike g.Roll(3); g.Roll(4); RollMany(16, 0); Assert.AreEqual(24, g.Score()); } publicint Score() { int score = 0; int roll = 0; for (int frame = 0; frame < 10; frame++) {         if(IsSpare(roll)) {     score += 10 + rolls[roll + 2]; } else {             score += rolls[roll] + rolls[roll + 1]; } roll += 2; } returnscore; } privatebool IsSpare(int roll) {     returnrolls[roll] +     rolls[roll + 1] == 10; } Failed Assert.AreEqual Expected:<24>. Actual:<17>
The Fourth test. ,[object Object]
ugly comment in conditional.
ugly expressions.publicint Score() {     intscore = 0; introll = 0; for(int frame = 0; frame < 10; frame++) { if(rolls[roll] == 10) // strike {     score += 10 + rolls[roll + 1]     + rolls[roll + 2]; roll++; } elseif (IsSpare(roll)) {     score += 10 + rolls[roll + 2]; roll += 2; } else {     score += rolls[roll] + rolls[roll + 1]; roll += 2; }     }     returnscore; } [TestMethod] publicvoid TestOneStrike() {     g.Roll(10); // strike g.Roll(3); g.Roll(4); RollMany(16, 0); Assert.AreEqual(24, g.Score()); }
The Fourth test. ,[object Object]
ugly comment in conditional.publicint Score() {     intscore = 0; introll = 0; for(int frame = 0; frame < 10; frame++) { if(rolls[roll] == 10) // strike {     score += 10 + StrikeBonus(roll); roll++; } elseif (IsSpare(roll)) {     score += 10 + SpareBonus(roll); roll += 2; } else {            score += SumOfBallsInFrame(roll); roll += 2; } } returnscore; } privateint SumOfBallsInFrame(int roll) {     returnrolls[roll] + rolls[roll + 1]; } privateint SpareBonus(int roll) {     returnrolls[roll + 2]; } privateint StrikeBonus(int roll) {     returnrolls[roll + 1] + rolls[roll + 2]; } [TestMethod] publicvoid TestOneStrike() {     g.Roll(10); // strike g.Roll(3); g.Roll(4); RollMany(16, 0); Assert.AreEqual(24, g.Score()); }

More Related Content

What's hot

Idiomatic Kotlin
Idiomatic KotlinIdiomatic Kotlin
Idiomatic Kotlinintelliyole
 
Java 8-streams-collectors-patterns
Java 8-streams-collectors-patternsJava 8-streams-collectors-patterns
Java 8-streams-collectors-patternsJosé Paumard
 
Domain Driven Design with the F# type System -- NDC London 2013
Domain Driven Design with the F# type System -- NDC London 2013Domain Driven Design with the F# type System -- NDC London 2013
Domain Driven Design with the F# type System -- NDC London 2013Scott Wlaschin
 
Javascript this keyword
Javascript this keywordJavascript this keyword
Javascript this keywordPham Huy Tung
 
Kotlin Bytecode Generation and Runtime Performance
Kotlin Bytecode Generation and Runtime PerformanceKotlin Bytecode Generation and Runtime Performance
Kotlin Bytecode Generation and Runtime Performanceintelliyole
 
Quickly Testing Qt Desktop Applications
Quickly Testing Qt Desktop ApplicationsQuickly Testing Qt Desktop Applications
Quickly Testing Qt Desktop ApplicationsClare Macrae
 
Control statements in java
Control statements in javaControl statements in java
Control statements in javaManojkumar C
 
Java 9/10/11 - What's new and why you should upgrade
Java 9/10/11 - What's new and why you should upgradeJava 9/10/11 - What's new and why you should upgrade
Java 9/10/11 - What's new and why you should upgradeSimone Bordet
 
Custom SRP and graphics workflows - Unite Copenhagen 2019
Custom SRP and graphics workflows - Unite Copenhagen 2019Custom SRP and graphics workflows - Unite Copenhagen 2019
Custom SRP and graphics workflows - Unite Copenhagen 2019Unity Technologies
 
An introduction to Google test framework
An introduction to Google test frameworkAn introduction to Google test framework
An introduction to Google test frameworkAbner Chih Yi Huang
 
Introduction to Rust language programming
Introduction to Rust language programmingIntroduction to Rust language programming
Introduction to Rust language programmingRodolfo Finochietti
 
Optimization Deep Dive: Unreal Engine 4 on Intel
Optimization Deep Dive: Unreal Engine 4 on IntelOptimization Deep Dive: Unreal Engine 4 on Intel
Optimization Deep Dive: Unreal Engine 4 on IntelIntel® Software
 
Angular Pipes Workshop
Angular Pipes WorkshopAngular Pipes Workshop
Angular Pipes WorkshopNir Kaufman
 
Unreal Engine Basics 01 - Game Framework
Unreal Engine Basics 01 - Game FrameworkUnreal Engine Basics 01 - Game Framework
Unreal Engine Basics 01 - Game FrameworkNick Pruehs
 

What's hot (20)

Idiomatic Kotlin
Idiomatic KotlinIdiomatic Kotlin
Idiomatic Kotlin
 
Java 8-streams-collectors-patterns
Java 8-streams-collectors-patternsJava 8-streams-collectors-patterns
Java 8-streams-collectors-patterns
 
Unit testing
Unit testingUnit testing
Unit testing
 
Domain Driven Design with the F# type System -- NDC London 2013
Domain Driven Design with the F# type System -- NDC London 2013Domain Driven Design with the F# type System -- NDC London 2013
Domain Driven Design with the F# type System -- NDC London 2013
 
Javascript this keyword
Javascript this keywordJavascript this keyword
Javascript this keyword
 
Core Java - Quiz Questions - Bug Hunt
Core Java - Quiz Questions - Bug HuntCore Java - Quiz Questions - Bug Hunt
Core Java - Quiz Questions - Bug Hunt
 
Kotlin Bytecode Generation and Runtime Performance
Kotlin Bytecode Generation and Runtime PerformanceKotlin Bytecode Generation and Runtime Performance
Kotlin Bytecode Generation and Runtime Performance
 
Quickly Testing Qt Desktop Applications
Quickly Testing Qt Desktop ApplicationsQuickly Testing Qt Desktop Applications
Quickly Testing Qt Desktop Applications
 
Java Class Design
Java Class DesignJava Class Design
Java Class Design
 
Control statements in java
Control statements in javaControl statements in java
Control statements in java
 
Java 9/10/11 - What's new and why you should upgrade
Java 9/10/11 - What's new and why you should upgradeJava 9/10/11 - What's new and why you should upgrade
Java 9/10/11 - What's new and why you should upgrade
 
Custom SRP and graphics workflows - Unite Copenhagen 2019
Custom SRP and graphics workflows - Unite Copenhagen 2019Custom SRP and graphics workflows - Unite Copenhagen 2019
Custom SRP and graphics workflows - Unite Copenhagen 2019
 
An introduction to Google test framework
An introduction to Google test frameworkAn introduction to Google test framework
An introduction to Google test framework
 
Git
GitGit
Git
 
Chapter17 of clean code
Chapter17 of clean codeChapter17 of clean code
Chapter17 of clean code
 
Introduction to Rust language programming
Introduction to Rust language programmingIntroduction to Rust language programming
Introduction to Rust language programming
 
Optimization Deep Dive: Unreal Engine 4 on Intel
Optimization Deep Dive: Unreal Engine 4 on IntelOptimization Deep Dive: Unreal Engine 4 on Intel
Optimization Deep Dive: Unreal Engine 4 on Intel
 
Angular Pipes Workshop
Angular Pipes WorkshopAngular Pipes Workshop
Angular Pipes Workshop
 
Unreal Engine Basics 01 - Game Framework
Unreal Engine Basics 01 - Game FrameworkUnreal Engine Basics 01 - Game Framework
Unreal Engine Basics 01 - Game Framework
 
Data Driven Game Design
Data Driven Game DesignData Driven Game Design
Data Driven Game Design
 

Viewers also liked

Viewers also liked (6)

Test driven development
Test driven developmentTest driven development
Test driven development
 
Fast Bowling
Fast Bowling Fast Bowling
Fast Bowling
 
Bowling
BowlingBowling
Bowling
 
Bowling
BowlingBowling
Bowling
 
Test and Behaviour Driven Development (TDD/BDD)
Test and Behaviour Driven Development (TDD/BDD)Test and Behaviour Driven Development (TDD/BDD)
Test and Behaviour Driven Development (TDD/BDD)
 
Test driven development in C
Test driven development in CTest driven development in C
Test driven development in C
 

Similar to Bowling Game Kata C#

Bowling game kata
Bowling game kataBowling game kata
Bowling game kataCarol Bruno
 
Bowling game kata
Bowling game kataBowling game kata
Bowling game kataJoe McCall
 
Bowling game kata
Bowling game kataBowling game kata
Bowling game kataRahman Ash
 
Test-Driven Development Fundamentals on Force.com
Test-Driven Development Fundamentals on Force.comTest-Driven Development Fundamentals on Force.com
Test-Driven Development Fundamentals on Force.comSalesforce Developers
 
I dont know what is wrong with this roulette program I cant seem.pdf
I dont know what is wrong with this roulette program I cant seem.pdfI dont know what is wrong with this roulette program I cant seem.pdf
I dont know what is wrong with this roulette program I cant seem.pdfarchanaemporium
 
You will write a multi-interface version of the well-known concentra.pdf
You will write a multi-interface version of the well-known concentra.pdfYou will write a multi-interface version of the well-known concentra.pdf
You will write a multi-interface version of the well-known concentra.pdfFashionColZone
 
Working with Layout Managers. Notes 1. In part 2, note that the Gam.pdf
Working with Layout Managers. Notes 1. In part 2, note that the Gam.pdfWorking with Layout Managers. Notes 1. In part 2, note that the Gam.pdf
Working with Layout Managers. Notes 1. In part 2, note that the Gam.pdfudit652068
 
The main class of the tictoe game looks like.public class Main {.pdf
The main class of the tictoe game looks like.public class Main {.pdfThe main class of the tictoe game looks like.public class Main {.pdf
The main class of the tictoe game looks like.public class Main {.pdfasif1401
 
Team public class Team {    private String teamId;    priva.pdf
Team public class Team {    private String teamId;    priva.pdfTeam public class Team {    private String teamId;    priva.pdf
Team public class Team {    private String teamId;    priva.pdfDEEPAKSONI562
 
The Ring programming language version 1.6 book - Part 55 of 189
The Ring programming language version 1.6 book - Part 55 of 189The Ring programming language version 1.6 book - Part 55 of 189
The Ring programming language version 1.6 book - Part 55 of 189Mahmoud Samir Fayed
 
This is Java,I am currently stumped on how to add a scoreboard for.pdf
This is Java,I am currently stumped on how to add a scoreboard for.pdfThis is Java,I am currently stumped on how to add a scoreboard for.pdf
This is Java,I am currently stumped on how to add a scoreboard for.pdfanjandavid
 
New Tools for a More Functional C++
New Tools for a More Functional C++New Tools for a More Functional C++
New Tools for a More Functional C++Sumant Tambe
 
package com.tictactoe; public class Main {public void play() {.pdf
package com.tictactoe; public class Main {public void play() {.pdfpackage com.tictactoe; public class Main {public void play() {.pdf
package com.tictactoe; public class Main {public void play() {.pdfinfo430661
 
The Ring programming language version 1.3 book - Part 43 of 88
The Ring programming language version 1.3 book - Part 43 of 88The Ring programming language version 1.3 book - Part 43 of 88
The Ring programming language version 1.3 book - Part 43 of 88Mahmoud Samir Fayed
 
In Java using Eclipse, Im suppose to write a class that encapsulat.pdf
In Java using Eclipse, Im suppose to write a class that encapsulat.pdfIn Java using Eclipse, Im suppose to write a class that encapsulat.pdf
In Java using Eclipse, Im suppose to write a class that encapsulat.pdfanjandavid
 
WINSEM2020-21_STS3105_SS_VL2020210500169_Reference_Material_I_04-Mar-2021_L14...
WINSEM2020-21_STS3105_SS_VL2020210500169_Reference_Material_I_04-Mar-2021_L14...WINSEM2020-21_STS3105_SS_VL2020210500169_Reference_Material_I_04-Mar-2021_L14...
WINSEM2020-21_STS3105_SS_VL2020210500169_Reference_Material_I_04-Mar-2021_L14...MaruMengesha
 
WINSEM2020-21_STS3105_SS_VL2020210500169_Reference_Material_I_01-Mar-2021_L12...
WINSEM2020-21_STS3105_SS_VL2020210500169_Reference_Material_I_01-Mar-2021_L12...WINSEM2020-21_STS3105_SS_VL2020210500169_Reference_Material_I_01-Mar-2021_L12...
WINSEM2020-21_STS3105_SS_VL2020210500169_Reference_Material_I_01-Mar-2021_L12...MaruMengesha
 
Testing a 2D Platformer with Spock
Testing a 2D Platformer with SpockTesting a 2D Platformer with Spock
Testing a 2D Platformer with SpockAlexander Tarlinder
 

Similar to Bowling Game Kata C# (20)

Bowling game kata
Bowling game kataBowling game kata
Bowling game kata
 
Bowling game kata
Bowling game kataBowling game kata
Bowling game kata
 
Bowling game kata
Bowling game kataBowling game kata
Bowling game kata
 
Test-Driven Development Fundamentals on Force.com
Test-Driven Development Fundamentals on Force.comTest-Driven Development Fundamentals on Force.com
Test-Driven Development Fundamentals on Force.com
 
I dont know what is wrong with this roulette program I cant seem.pdf
I dont know what is wrong with this roulette program I cant seem.pdfI dont know what is wrong with this roulette program I cant seem.pdf
I dont know what is wrong with this roulette program I cant seem.pdf
 
You will write a multi-interface version of the well-known concentra.pdf
You will write a multi-interface version of the well-known concentra.pdfYou will write a multi-interface version of the well-known concentra.pdf
You will write a multi-interface version of the well-known concentra.pdf
 
Working with Layout Managers. Notes 1. In part 2, note that the Gam.pdf
Working with Layout Managers. Notes 1. In part 2, note that the Gam.pdfWorking with Layout Managers. Notes 1. In part 2, note that the Gam.pdf
Working with Layout Managers. Notes 1. In part 2, note that the Gam.pdf
 
The main class of the tictoe game looks like.public class Main {.pdf
The main class of the tictoe game looks like.public class Main {.pdfThe main class of the tictoe game looks like.public class Main {.pdf
The main class of the tictoe game looks like.public class Main {.pdf
 
Driver class
Driver classDriver class
Driver class
 
Team public class Team {    private String teamId;    priva.pdf
Team public class Team {    private String teamId;    priva.pdfTeam public class Team {    private String teamId;    priva.pdf
Team public class Team {    private String teamId;    priva.pdf
 
The Ring programming language version 1.6 book - Part 55 of 189
The Ring programming language version 1.6 book - Part 55 of 189The Ring programming language version 1.6 book - Part 55 of 189
The Ring programming language version 1.6 book - Part 55 of 189
 
This is Java,I am currently stumped on how to add a scoreboard for.pdf
This is Java,I am currently stumped on how to add a scoreboard for.pdfThis is Java,I am currently stumped on how to add a scoreboard for.pdf
This is Java,I am currently stumped on how to add a scoreboard for.pdf
 
New Tools for a More Functional C++
New Tools for a More Functional C++New Tools for a More Functional C++
New Tools for a More Functional C++
 
Parameters
ParametersParameters
Parameters
 
package com.tictactoe; public class Main {public void play() {.pdf
package com.tictactoe; public class Main {public void play() {.pdfpackage com.tictactoe; public class Main {public void play() {.pdf
package com.tictactoe; public class Main {public void play() {.pdf
 
The Ring programming language version 1.3 book - Part 43 of 88
The Ring programming language version 1.3 book - Part 43 of 88The Ring programming language version 1.3 book - Part 43 of 88
The Ring programming language version 1.3 book - Part 43 of 88
 
In Java using Eclipse, Im suppose to write a class that encapsulat.pdf
In Java using Eclipse, Im suppose to write a class that encapsulat.pdfIn Java using Eclipse, Im suppose to write a class that encapsulat.pdf
In Java using Eclipse, Im suppose to write a class that encapsulat.pdf
 
WINSEM2020-21_STS3105_SS_VL2020210500169_Reference_Material_I_04-Mar-2021_L14...
WINSEM2020-21_STS3105_SS_VL2020210500169_Reference_Material_I_04-Mar-2021_L14...WINSEM2020-21_STS3105_SS_VL2020210500169_Reference_Material_I_04-Mar-2021_L14...
WINSEM2020-21_STS3105_SS_VL2020210500169_Reference_Material_I_04-Mar-2021_L14...
 
WINSEM2020-21_STS3105_SS_VL2020210500169_Reference_Material_I_01-Mar-2021_L12...
WINSEM2020-21_STS3105_SS_VL2020210500169_Reference_Material_I_01-Mar-2021_L12...WINSEM2020-21_STS3105_SS_VL2020210500169_Reference_Material_I_01-Mar-2021_L12...
WINSEM2020-21_STS3105_SS_VL2020210500169_Reference_Material_I_01-Mar-2021_L12...
 
Testing a 2D Platformer with Spock
Testing a 2D Platformer with SpockTesting a 2D Platformer with Spock
Testing a 2D Platformer with Spock
 

Recently uploaded

Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FMESafe Software
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherRemote DBA Services
 
Exploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusExploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusZilliz
 
Vector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptxVector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptxRemote DBA Services
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native ApplicationsWSO2
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Victor Rentea
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobeapidays
 
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot ModelMcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot ModelDeepika Singh
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistandanishmna97
 
ICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesrafiqahmad00786416
 
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...Angeliki Cooney
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MIND CTI
 
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWEREMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWERMadyBayot
 
Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)Zilliz
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodJuan lago vázquez
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc
 
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Orbitshub
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxRustici Software
 
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamUiPathCommunity
 

Recently uploaded (20)

Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
Exploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusExploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with Milvus
 
Vector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptxVector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptx
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot ModelMcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistan
 
ICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesICT role in 21st century education and its challenges
ICT role in 21st century education and its challenges
 
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWEREMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
 
Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptx
 
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
 

Bowling Game Kata C#

  • 1.
  • 2. Adapted for C# 4.0 (With Visual Studio 2010) By Dan Stewart dan@stewshack.com
  • 3. Scoring Bowling. The game consists of 10 frames as shown above. In each frame the player has two opportunities to knock down 10 pins. The score for the frame is the total number of pins knocked down, plus bonuses for strikes and spares. 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.
  • 4. A quick design session Clearly we need the Game class.
  • 5. A quick design session A game has 10 frames.
  • 6. A quick design session A frame has 1 or two rolls.
  • 7. A quick design session The tenth frame has two or three rolls. It is different from all the other frames.
  • 8. A quick design session The score function must include all the frames, and calculate all their scores.
  • 9. A quick design session The score for a spare or a strike depends on the frame’s successor
  • 10. Begin. Create a console application named BowlingGame Add a MSTest project named BowlingGameTest to the solution
  • 11. Begin. Add a unit test named GameTest to the project using Microsoft.VisualStudio.TestTools.UnitTesting; namespace BowlingGameTest { [TestClass] publicclassGameTest { privateTestContext testContextInstance; publicTestContext TestContext { get { return testContextInstance; } set { testContextInstance = value; } } [TestMethod] publicvoid TestMethod1() { } } }
  • 12. The first test. [TestMethod] publicvoidTestGutterGame() { Game g = new Game(); }
  • 13. The first test. namespaceBowlingGame { publicclassGame { } } [TestMethod] publicvoidTestGutterGame() { Game g = new Game(); }
  • 14. The first test. [TestMethod] publicvoidTestGutterGame() { Game g = new Game(); } publicclassGame { }
  • 15. The first test. [TestMethod] publicvoidTestGutterGame() { Gameg = newGame(); for(int i = 0; i < 20; i++) { g.Roll(0); } } publicclassGame { }
  • 16. The first test. public class Game { publicvoid Roll(int p) { thrownewSystem.NotImplementedException(); } } [TestMethod] publicvoidTestGutterGame() { Gameg = newGame(); for(int i = 0; i < 20; i++) { g.Roll(0); } }
  • 17. The first test. [TestMethod] publicvoidTestGutterGame() { Gameg = newGame(); for(int i = 0; i < 20; i++) { g.Roll(0); } Assert.AreEqual(0, g.Score()); } public class Game { publicvoid Roll(int p) { thrownewSystem.NotImplementedException(); } }
  • 18. The first test. [TestMethod] publicvoid TestGutterGame() { Gameg = newGame(); for(int i = 0; i < 20; i++) { g.Roll(0); } Assert.AreEqual(0, g.Score()); } publicclassGame { publicvoid Roll(int p) { thrownew System.NotImplementedException(); } publicobject Score() { thrownew System.NotImplementedException(); } } Failed TestGutterGame threw exception
  • 19. The first test. [TestMethod] publicvoid TestGutterGame() { Gameg = newGame(); for(int i = 0; i < 20; i++) { g.Roll(0); } Assert.AreEqual(0, g.Score); } publicclassGame { privateint score; publicvoid Roll(int pins) { } publicintScore() { returnscore; } }
  • 20. The Second test. [TestMethod] publicvoid TestAllOnes() { Gameg = newGame(); for(int i = 0; i < 20; i++) { g.Roll(1); } Assert.AreEqual(20, g.Score()); } publicclassGame { privateint score; publicvoid Roll(int pins) { } publicintScore() { returnscore; } }
  • 21. The Second test. - Game creation is duplicated - roll loop is duplicated [TestMethod] publicvoid TestAllOnes() { Gameg = newGame(); for(int i = 0; i < 20; i++) { g.Roll(1); } Assert.AreEqual(20, g.Score()); } publicclassGame { privateint score; publicvoid Roll(int pins) { } publicintScore() { returnscore; } }
  • 22. The Second test. - Game creation is duplicated - roll loop is duplicated [TestMethod] publicvoid TestAllOnes() { Gameg = newGame(); for(int i = 0; i < 20; i++) { g.Roll(1); } Assert.AreEqual(20, g.Score()); } publicclassGame { privateint score; publicvoid Roll(int pins) { } publicintScore() { return score; } } Assert.AreEqual failed. Expected:<20>. Actual:<0>.
  • 23. The Second test. - roll loop is duplicated privateGame g; [TestInitialize] publicvoid Initialize() { g = newGame(); } [TestCleanup] publicvoid Cleanup() { g = null; } [TestMethod] publicvoid TestGutterGame() { for(int i = 0; i < 20; i++) { g.Roll(0); } Assert.AreEqual(0, g.Score()); } [TestMethod] publicvoid TestAllOnes() { for(int i = 0; i < 20; i++) { g.Roll(1); } Assert.AreEqual(20, g.Score()); } publicclassGame { privateint score; publicvoid Roll(int pins) { score += pins; } publicint Score() { return score; } }
  • 24. The Second test. - roll loop is duplicated [TestMethod] publicvoid TestGutterGame() { int rolls = 20; intpins = 0; for(int i = 0; i < rolls; i++) { g.Roll(pins); } Assert.AreEqual(0, g.Score()); } publicclassGame { privateint score; publicvoid Roll(int pins) { score += pins; } publicint Score() { return score; } }
  • 25. The Second test. - roll loop is duplicated [TestMethod] publicvoid TestGutterGame() { int rolls = 20; intpins = 0; RollMany(rolls, pins); for(int i = 0; i < rolls; i++) { g.Roll(pins); } Assert.AreEqual(0, g.Score()); } publicclassGame { privateint score; publicvoid Roll(int pins) { score += pins; } publicint Score() { return score; } }
  • 26. The Second test. publicclassGame { privateint score; publicvoid Roll(int pins) { score += pins; } publicint Score() { return score; } } [TestMethod] publicvoid TestGutterGame() { RollMany(20, 0); Assert.AreEqual(0, g.Score()); } privatevoid RollMany(introlls, int pins) { for(int i = 0; i < rolls; i++) { g.Roll(pins); } }
  • 27. The Second test. [TestMethod] publicvoid TestGutterGame() { RollMany(20, 0); Assert.AreEqual(0, g.Score()); } [TestMethod] publicvoid TestAllOnes() { RollMany(20, 1); Assert.AreEqual(20, g.Score()); } privatevoid RollMany(int rolls, int pins) { for(int i = 0; i < rolls; i++) { g.Roll(pins); } } publicclassGame { privateint score; publicvoid Roll(int pins) { score += pins; } publicint Score() { return score; } }
  • 28. The Third test. - ugly comment in test. [TestMethod] publicvoid TestOneSpare() { g.Roll(5); g.Roll(5); // spare g.Roll(3); RollMany(17, 0); Assert.AreEqual(16, g.Score()); } publicclassGame { privateint score; publicvoid Roll(int pins) { score += pins; } publicint Score() { return score; } } Failed Assert.AreEqual Expected:<16>. Actual:<13>
  • 29. The Third test. - ugly comment in test. publicclassGame { privateint score; publicvoid Roll(int pins) { score += pins; } publicint Score() { return score; } } [TestMethod] publicvoid TestOneSpare() { g.Roll(5); g.Roll(5); // spare g.Roll(3); RollMany(17, 0); Assert.AreEqual(16, g.Score()); } tempted to use flag to remember previous roll. So design must be wrong. Failed Assert.AreEqual Expected:<16>. Actual:<13>
  • 30. The Third test. - ugly comment in test. Roll() calculates score, but name does not imply that. publicclassGame { privateint score; publicvoid Roll(int pins) { score += pins; } publicint Score() { return score; } } [TestMethod] publicvoid TestOneSpare() { g.Roll(5); g.Roll(5); // spare g.Roll(3); RollMany(17, 0); Assert.AreEqual(16, g.Score); } Score() does not calculate score, but name implies that it does. Design is wrong. Responsibilities are misplaced. Failed Assert.AreEqual Expected:<16>. Actual:<13>
  • 31. The Third test. - ugly comment in test. [TestMethod] publicvoid TestOneSpare() { g.Roll(5); g.Roll(5); // spare g.Roll(3); RollMany(17, 0); //Assert.AreEqual(16, g.Score()); Assert.Inconclusive(); } publicclassGame { privateint score; publicvoid Roll(int pins) { score += pins; } publicint Score() { return score; } }
  • 32. The Third test. - ugly comment in test. publicclassGame { privateint score; privateint[] rolls = newint[21]; privateint currentRoll; publicvoid Roll(int pins) { rolls[currentRoll++] = pins; score += pins; } publicint Score() { return score; } } [TestMethod] publicvoid TestOneSpare() { g.Roll(5); g.Roll(5); // spare g.Roll(3); RollMany(17, 0); //Assert.AreEqual(16, g.Score()); Assert.Inconclusive(); }
  • 33. The Third test. - ugly comment in test. publicclassGame { privateint[] rolls = newint[21]; privateint currentRoll; publicvoid Roll(int pins) { rolls[currentRoll++] = pins; } publicint Score() { int score = 0; for (int i = 0; i < rolls.Length; i++) { score += rolls[i]; } return score; } } [TestMethod] publicvoid TestOneSpare() { g.Roll(5); g.Roll(5); // spare g.Roll(3); RollMany(17, 0); //Assert.AreEqual(16, g.Score()); Assert.Inconclusive(); }
  • 34. The Third test. - ugly comment in test. [TestMethod] publicvoid TestOneSpare() { g.Roll(5); g.Roll(5); // spare g.Roll(3); RollMany(17, 0); Assert.AreEqual(16, g.Score()); } publicclassGame { privateint[] rolls = newint[21]; privateint currentRoll; publicvoid Roll(int pins) { rolls[currentRoll++] = pins; } publicint Score() { int score = 0; for (int i = 0; i < rolls.Length; i++) { score += rolls[i]; } return score; } } Failed Assert.AreEqual Expected:<16>. Actual:<13>
  • 35. The Third test. - ugly comment in test. publicint Score() { int score = 0; for (int i = 0; i < rolls.Length; i++) { // spare if(rolls[i] + rolls[i+1] == 10) { score += ... } score += rolls[i]; } return score; } [TestMethod] publicvoid TestOneSpare() { g.Roll(5); g.Roll(5); // spare g.Roll(3); RollMany(17, 0); Assert.AreEqual(16, g.Score()); } This isn’t going to work because i might not refer to the first ball of the frame. Design is still wrong. Need to walk through array two balls (one frame) at a time. Failed Assert.AreEqual Expected:<16>. Actual:<13>
  • 36. The Third test. - ugly comment in test. publicclassGame { privateint[] rolls = newint[21]; privateint currentRoll; publicvoid Roll(int pins) { rolls[currentRoll++] = pins; } publicint Score() { int score = 0; for (int i = 0; i < rolls.Length; i++) { score += rolls[i]; } return score; } } [TestMethod] publicvoid TestOneSpare() { g.Roll(5); g.Roll(5); // spare g.Roll(3); RollMany(17, 0); //Assert.AreEqual(16, g.Score()); Assert.Inconclusive(); }
  • 37. The Third test. - ugly comment in test. publicint Score() { int score = 0; int roll = 0; for (int frame = 0; frame < 10; frame++) { score += rolls[roll] + rolls[roll + 1]; roll += 2; } returnscore; } [TestMethod] publicvoid TestOneSpare() { g.Roll(5); g.Roll(5); // spare g.Roll(3); RollMany(17, 0); //Assert.AreEqual(16, g.Score()); Assert.Inconclusive(); }
  • 38. The Third test. - ugly comment in test. [TestMethod] publicvoid TestOneSpare() { g.Roll(5); g.Roll(5); // spare g.Roll(3); RollMany(17, 0); Assert.AreEqual(16, g.Score()); } publicint Score() { int score = 0; int roll = 0; for (int frame = 0; frame < 10; frame++) { score += rolls[roll] + rolls[roll + 1]; roll += 2; } returnscore; } Failed Assert.AreEqual Expected:<16>. Actual:<13>
  • 39. The Third test. - ugly comment in test. publicint Score() { int score = 0; int roll = 0; for (int frame = 0; frame < 10; frame++) { // spare if (rolls[roll] + rolls[roll + 1] == 10) { score += 10 + rolls[roll + 2]; } else { score += rolls[roll] + rolls[roll + 1]; } roll += 2; } return score; } [TestMethod] publicvoid TestOneSpare() { g.Roll(5); g.Roll(5); // spare g.Roll(3); RollMany(17, 0); Assert.AreEqual(16, g.Score()); }
  • 40.
  • 41. ugly comment in conditional.publicint Score() { int score = 0; int roll = 0; for (int frame = 0; frame < 10; frame++) { // spare if (rolls[roll] + rolls[roll + 1] == 10) { score += 10 + rolls[roll + 2]; } else { score += rolls[roll] + rolls[roll + 1]; } roll += 2; } return score; } [TestMethod] publicvoid TestOneSpare() { g.Roll(5); g.Roll(5); // spare g.Roll(3); RollMany(17, 0); Assert.AreEqual(16, g.Score()); }
  • 42. The Third test. - ugly comment in test. publicint Score() { int score = 0; int roll = 0; for (int frame = 0; frame < 10; frame++) { if(IsSpare(roll)) { score += 10 + rolls[roll + 2]; } else { score += rolls[roll] + rolls[roll + 1]; } roll += 2; } returnscore; } privatebool IsSpare(int roll) { returnrolls[roll] + rolls[roll + 1] == 10; } [TestMethod] publicvoid TestOneSpare() { g.Roll(5); g.Roll(5); // spare g.Roll(3); RollMany(17, 0); Assert.AreEqual(16, g.Score()); }
  • 43. The Third test. [TestMethod] publicvoid TestOneSpare() { RollSpare(); g.Roll(3); RollMany(17, 0); Assert.AreEqual(16, g.Score()); } privatevoid RollSpare() { g.Roll(5); g.Roll(5); } publicint Score() { int score = 0; int roll = 0; for (int frame = 0; frame < 10; frame++) { if(IsSpare(roll)) { score += 10 + rolls[roll + 2]; } else { score += rolls[roll] + rolls[roll + 1]; } roll += 2; } returnscore; } privatebool IsSpare(int roll) { returnrolls[roll] + rolls[roll + 1] == 10; }
  • 44. The Fourth test. - ugly comment in testOneStrike. [TestMethod] publicvoid TestOneStrike() { g.Roll(10); // strike g.Roll(3); g.Roll(4); RollMany(16, 0); Assert.AreEqual(24, g.Score()); } publicint Score() { int score = 0; int roll = 0; for (int frame = 0; frame < 10; frame++) { if(IsSpare(roll)) { score += 10 + rolls[roll + 2]; } else { score += rolls[roll] + rolls[roll + 1]; } roll += 2; } returnscore; } privatebool IsSpare(int roll) { returnrolls[roll] + rolls[roll + 1] == 10; } Failed Assert.AreEqual Expected:<24>. Actual:<17>
  • 45.
  • 46. ugly comment in conditional.
  • 47. ugly expressions.publicint Score() { intscore = 0; introll = 0; for(int frame = 0; frame < 10; frame++) { if(rolls[roll] == 10) // strike { score += 10 + rolls[roll + 1] + rolls[roll + 2]; roll++; } elseif (IsSpare(roll)) { score += 10 + rolls[roll + 2]; roll += 2; } else { score += rolls[roll] + rolls[roll + 1]; roll += 2; } } returnscore; } [TestMethod] publicvoid TestOneStrike() { g.Roll(10); // strike g.Roll(3); g.Roll(4); RollMany(16, 0); Assert.AreEqual(24, g.Score()); }
  • 48.
  • 49. ugly comment in conditional.publicint Score() { intscore = 0; introll = 0; for(int frame = 0; frame < 10; frame++) { if(rolls[roll] == 10) // strike { score += 10 + StrikeBonus(roll); roll++; } elseif (IsSpare(roll)) { score += 10 + SpareBonus(roll); roll += 2; } else { score += SumOfBallsInFrame(roll); roll += 2; } } returnscore; } privateint SumOfBallsInFrame(int roll) { returnrolls[roll] + rolls[roll + 1]; } privateint SpareBonus(int roll) { returnrolls[roll + 2]; } privateint StrikeBonus(int roll) { returnrolls[roll + 1] + rolls[roll + 2]; } [TestMethod] publicvoid TestOneStrike() { g.Roll(10); // strike g.Roll(3); g.Roll(4); RollMany(16, 0); Assert.AreEqual(24, g.Score()); }
  • 50. The Fourth test. - ugly comment in testOneStrike. publicint Score() { int score = 0; int roll = 0; for (int frame = 0; frame < 10; frame++) { if(IsStrike(roll)) { score += 10 + StrikeBonus(roll); roll++; } elseif (IsSpare(roll)) { score += 10 + SpareBonus(roll); roll += 2; } else { score += SumOfBallsInFrame(roll); roll += 2; } } returnscore; } privatebool IsStrike(int roll) { returnrolls[roll] == 10; } [TestMethod] publicvoid TestOneStrike() { g.Roll(10); // strike g.Roll(3); g.Roll(4); RollMany(16, 0); Assert.AreEqual(24, g.Score()); }
  • 51. The Fourth test. [TestMethod] publicvoid TestOneStrike() { RollStrike(); g.Roll(3); g.Roll(4); RollMany(16, 0); Assert.AreEqual(24, g.Score()); } privatevoid RollStrike() { g.Roll(10); } publicint Score() { int score = 0; int roll = 0; for (int frame = 0; frame < 10; frame++) { if(IsStrike(roll)) { score += 10 + StrikeBonus(roll); roll++; } elseif (IsSpare(roll)) { score += 10 + SpareBonus(roll); roll += 2; } else { score += SumOfBallsInFrame(roll); roll += 2; } } returnscore; }
  • 52. The Fifth test. [TestMethod] publicvoid TestPerfectGame() { RollMany(12, 10); Assert.AreEqual(300, g.Score()); } publicint Score() { int score = 0; int roll = 0; for (int frame = 0; frame < 10; frame++) { if(IsStrike(roll)) { score += 10 + StrikeBonus(roll); roll++; } elseif (IsSpare(roll)) { score += 10 + SpareBonus(roll); roll += 2; } else { score += SumOfBallsInFrame(roll); roll += 2; } } returnscore; }

Editor's Notes

  1. First, I would like to thank Uncle Bob Martin and Object Mentor for the bowling game kata.
  2. My name is Dan Stewart. My e-mail is dan@stewshack.com. I welcome your feedback on my version of the Bowling Game.