C++ Bowling Kata Result
Posted by Brett Schuchert Tue, 27 Oct 2009 20:37:00 GMT
I’m teaching a TDD and Refactoring class this week using C++. Since I had not recently wrote the bowling kata in C++, I figured it was about time to do it again.
Unlike the previous Scala version, this one only addresses the happy-path. I do not consider throwing too many balls or scoring too many pins in any frame. However, having just written this in Scala, I’m sure I could do something similar in C++.
I just switched to CppUTest 2.0 and something I noticed is that if you use <vector> or other std-based classes, you need to make sure to include those first before including <CppUTest/TestHarness.h>. This is because CppUTest overloads new and delete, which causes havoc with the std-based classes. No big deal, I just made sure to include that file as the last header (rather than the first, which is what I used to do).
Here are the various files:
RunAllTests.cpp
1
2
3
4
5
|
#include <CppUTest/CommandLineTestRunner.h>
int main(int argc, char** argv) {
CommandLineTestRunner::RunAllTests(argc, argv);
}
|
BowlingScoreCardTest.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
|
#include "BowlingScoreCard.h"
#include <CppUTest/TestHarness.h>
TEST_GROUP(BowlingScoreCard) {
BowlingScoreCard* card;
TEST_SETUP() {
card = new BowlingScoreCard;
}
TEST_TEARDOWN() {
delete card;
}
void throwOne(int value) {
card->recordThrow(value);
}
void throwMany(int rolls, int value) {
for(int i = 0; i < rolls; ++i)
throwOne(value);
}
void confirmScoreIs(int expected) {
LONGS_EQUAL(expected, card->score());
}
};
TEST(BowlingScoreCard, noRollsGame) {
confirmScoreIs(0);
}
TEST(BowlingScoreCard, throwAll0s) {
throwMany(20, 0);
confirmScoreIs(0);
}
TEST(BowlingScoreCard, throwAll1s) {
throwMany(20, 1);
confirmScoreIs(20);
}
TEST(BowlingScoreCard, throwOneSpare) {
throwOne(7);
throwOne(3);
throwOne(6);
throwMany(17, 0);
confirmScoreIs(22);
}
TEST(BowlingScoreCard, all5sthrown) {
throwMany(21, 5);
confirmScoreIs(150);
}
TEST(BowlingScoreCard, throwOneStrike) {
throwOne(10);
throwOne(4);
throwOne(3);
confirmScoreIs(24);
}
TEST(BowlingScoreCard, perfectGame) {
throwMany(12, 10);
confirmScoreIs(300);
}
TEST(BowlingScoreCard, dutch200StrikeSpare) {
for(int i = 0; i < 10; ++i) {
throwOne(10);
throwMany(2, 5);
}
throwOne(10);
confirmScoreIs(200);
}
TEST(BowlingScoreCard, dutch200SpareStrike) {
for(int i = 0; i < 10; ++i) {
throwMany(2, 5);
throwOne(10);
}
throwMany(2, 5);
confirmScoreIs(200);
}
|
BowlingScoreCard.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
#pragma once
#ifndef BOWLING_SCORE_CARD_H
#define BOWLING_SCORE_CARD_H
#include <vector>
using namespace std;
class BowlingScoreCard
{
public:
enum { Frames = 10, Mark = 10 };
BowlingScoreCard();
virtual ~BowlingScoreCard();
int score();
void recordThrow(int roll);
private:
typedef vector<int> v_int;
typedef v_int::size_type size_type;
int scoreFrameAt(size_type index);
int nextTwoRollsSummed(size_type index);
int scoreAt(size_type index);
int frameSizeAt(size_type index);
bool isStrikeAt(size_type index);
bool isSpareAt(size_type index);
int scoreStrikeAt(size_type index);
int scoreSpareAt(size_type index);
v_int rolls;
};
#endif
|
BowlingScoreCard.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
|
#include "BowlingScoreCard.h"
BowlingScoreCard::BowlingScoreCard() {
}
BowlingScoreCard::~BowlingScoreCard() {
}
int BowlingScoreCard::score() {
int score = 0;
for(int index = 0, frame = 0; frame < Frames; ++frame) {
score += scoreFrameAt(index);
index += frameSizeAt(index);
}
return score;
}
int BowlingScoreCard::scoreFrameAt(size_type index) {
if(isStrikeAt(index))
return scoreStrikeAt(index);
else if(isSpareAt(index))
return scoreSpareAt(index);
return nextTwoRollsSummed(index);
}
bool BowlingScoreCard::isStrikeAt(size_type index) {
return scoreAt(index) == Mark;
}
bool BowlingScoreCard::isSpareAt(size_type index) {
return !isStrikeAt(index) && nextTwoRollsSummed(index) == Mark;
}
int BowlingScoreCard::scoreStrikeAt(size_type index) {
return Mark + nextTwoRollsSummed(index + 1);
}
int BowlingScoreCard::scoreSpareAt(size_type index) {
return Mark + scoreAt(index + 2);
}
int BowlingScoreCard::frameSizeAt(size_type index) {
if(scoreAt(index) == Mark)
return 1;
return 2;
}
int BowlingScoreCard::nextTwoRollsSummed(size_type index) {
return scoreAt(index) + scoreAt(index + 1);
}
int BowlingScoreCard::scoreAt(size_type index) {
return index < rolls.size() ? rolls[index] : 0;
}
void BowlingScoreCard::recordThrow(int roll) {
rolls.push_back(roll);
}
|
I sure do miss refactoring tools!-)
“I sure do miss refactoring tools!-)” It shows in your code :) Is this C++ or for a specific implementation of C++ as “pragma once” when not recognised by the compiler is allowed to do anything it wants.
I have not used this framework yet many other C++ frameworks and they all return a result of the tests do you not want this information returned from main?
Files do not end with an extra line, yet I am assuming this is an error when posting to the blog.
BowlingScoreCard.h pollutes the global namespace via the horrible “using namespace std”!
There is no need for BowlingScoreCard constructor as it does nothing the default does not, also why the virtual destructor are you expecting to derive from the class as you will pay for a vtable(on most implementations).
The function scoreAt looks really wrong to me. If you are indexing out of range that is an error and should not return zero, maybe use vector’s at which throws on out of bounds.
Should the score function be using the enum constant frame as it is quite possible you can throw more times than Frame and this is not accounted for, therefore would it not be better to do some checking in throw and use iterators or at least the vectors size to calculate the score. I know you mention this but still it is wrong.
Also why it the constant an enum and not a const int. With forward thinking in mind and IIRC enums will not be promoted so easily to in C++0x.
You have loops in your tests should they be there?
Stan,
The #pragma once should be safely ignored by ANSI compliant compilers that do not understand it. In general, #pragmas that are not understood should be ignored. What compiler is giving you problems? Notice that I also put in the standard conditional include guards, just in case I have an older compiler. This is boilerplate C++ code, so I don’t get your point.
When I run the tests they either pass or fail. If they pass, I don’t need more information. If they fail, then I first need to know which tests failed. I would know that from execution and I would start there. So what are you looking for?
Files not ending with a blank line? Was that really necessary? I can copy the code into an editor as is (vi is my editor of choice), save it and go. Are you picking nits or is there something else you’re trying to get at?
The global pollution of the namespace is a good point. For this little practice session I didn’t care. In fact, where I used it, I was silly to do so anyway as I used nested typedefs.
I do not agree with your comment about the ctor. Auto-generated ctors lead to larger .o files and code on many compilers. As for the virtual dtor, I add that. I don’t work in embedded systems, so the addition of the vtable is not much of an issue. If I were working in an embedded system, I’d be a lot more picky about the use of virtual methods anywhere. But I’d still explicitly code both of them rather than let the compiler regenerate the code everywhere instances are constructed.
I do not agree with your comment about scoreAt. Given my current system definition (its tests), the scoreAt works fine. I can score a bowling game by hand with an empty card. The array is empty. Asking for the score at a location that does not yet exist is a score of 0. Putting validation of the sort your suggesting at such a low level seems backwards. I would prefer to validate input right as I get it. That method is a private method used for internal purposes only, so its definition is perfectly fine as it is. Its implementation falls under the category of the “null-object pattern”.
Loops in tests seem fine to me. I’m trying to fill out a game. I could write several lines or a loop or maybe a variable argument method. I’ve used loops in tests in real systems. Your comment sounds like a context-free rule, which I tend to question.
I agree on not using the const int (actually static const int, right).
As for the score function taking into account extra rolls, several comments: 1. I wrote in the blog, this is happy path. 2. I also wrote in the blog that I had already posted an example with validation in Scala – specifically too many throws. 3. I would not allow the score card to have more than the allowed number of throws, so the loop is fine.
And notice as I wrote the scoreAt method, I am able to score the entire game if I want.So we can agree to disagree.
As for not using iterators, that is a side-effect of how I’ve stored the scores. In the original bowling kata, uncle bob only uses one array slot for a strike. I’ve done that as well. So if I use an iterator, I need to look ahead. Since for a std::vector an iterator is really just an int*, I can just use it along with indexes. But if look at the code, the frame can start on an even or odd index depending on the strikes. I know this is strange, I was just repeating form. I’ve done it this way and I’ve used 2 cells for all frames (other than the 10th frame) as well. It’s 6 of one half-dozen the other as far as I’m concerned. In any event, in this case if I used an iterator, I’d end up modifying the iterator by some amount. The iterator doesn’t express the solution any better than the index. I could have actually done that by setting the iterator ahead a number of indexes depending on the structure of the cells (which I did using an index instead of an iterator), but that’s taking knowledge of the underlying implementation of the iterator, which I think is a worse idea.
@Bret,
These Katas are great! The only thing that I haven’t seen from the bowling is the evolution of the scorer to an actual recognizer, like you would have for regexp.
Anytime I see that I’m creating methods private or public that want to ask questions of internal state of my object, it starts to look like a code smell. I believe there is another object in there asking to be set free. Tell don’t ask.
Thanks for the C++.
@Brett:
AFAIK, nothing in the C++ standard states that the iterator for std::vector is a bare pointer.
@UncleBob:
About the include order in C++, I personally usually include the lowest layers last (i.e. the STL last). If I did this the other way around (lowest layers first), it may hide the fact that some of my .h files don’t stand for themselves, e.g. do not include or when they should.
Oops, I don’t know why,, but I thought the blog was written by Uncle Bob. Both comments were for Brett.
And the last line should read : do not include <vector> or <list> when they should.
@L – is that from DeathNote?
I am not certain, but I do know that the access times (insertion, lookup) for vector are defined. Lookup, [], is O 1 (constant time), for example.
Regarding include order, it turns out that using the latest version of CppUTest requires (in the test file), including or at least after any chance of things like , since it overloads global new/delete.
No, I’m not DeathNote. I’m a long date follower of this blog but a new commenter, nice to meet you, Brett :)
Thank you for the tip on CppUTest. I know things can get pretty nasty when you fiddle with the guts of a language.
Thank you for this version of the Kata. Seeing some good C++ from time to time is refreshing.
By the way, (it’s personal taste again) why not use boost::shared_ptr instead of a base pointer in the test class? You get nullity checking and reference counting almost for free.
@L,
I really like the boost library. I used it quite a bit when porting the projects for one of our Java classes to C++. However, I have no good reason for not using it in this project. Actually, I didn’t even consider it.
All I have to do is update the list of directories to search for include files. I probably didn’t consider it because the takes care of dynamic allocation in the scorer and the only other place I use new is in a controlled environment, the test.
But really, didn’t even consider it. Not exactly sure why. If I were to work on a real project, the boos library is the first thing I’d bring into the mix. I like it.
c++ is a difficult book, as i know
Welcome to Freshstyleshop, the hottest urban clothing site on the net! We offer great products from Gucci sneakers, prada sneakers, LV shoes, True Religion Jeans and many more! Our selection of products are always increasing for the fact that we have new items added weekly to our selection. All products on our site are already marked down 40-60% off retail price. Freshstyleshop also backs all its orders with a 110% satisfaction guarantee, making sure that our customers are left satisfied with the hottest products on the net.
If not, could you please send me the code so we can continue to play with it? Thanks.
Good information about this topic. I really very useful and helpfulness article. I tried to your tips is a very successful on the worked.
Good information about this topic. I really very useful and helpfulness article. I tried to your tips is a very successful on the worked.
Files not ending with a blank line? Was that really necessary? I can copy the code into an editor as is (vi is my editor of choice), save it and go. Are you picking nits or is there something else you’re trying to get at?
The global pollution of the namespace is a good point. For this little practice session I didn’t care. In fact, where I used it, I was silly to do so anyway as I used nested typedefs.
I do not agree with your comment about the ctor. Auto-generated ctors lead to larger .o files and code on many compilers. As for the virtual dtor, I add that. I don’t work in embedded systems, so the addition of the vtable is not much of an issue. If I were working in an embedded system, I’d be a lot more picky about the use of virtual methods anywhere. But I’d still explicitly code both of them rather than let the compiler regenerate the code everywhere instances are constructed.cheap VPS
Wow – these are absolutely fantastic. We love Creative Commons and thank you for putting Free Hosting With MYSQL
Thank you so much for your work on keeping the site together and keeping these flowing. branded shopping
Well , the view of the passage is totally correct gucci mens ,your details is really reasonable gucci belt for men and you guy give us valuable informative post, size11 gucci sneakers I totally agree the standpoint of upstairs. I often discount gucci jeans surfing on this forum classic gucci wallets when I m free and I find there are so much good information we can learn in this forum!
so good post i like it china nfl jerseys
gucci wallet, gucci wallets, mens gucci wallets, women gucci wallets.
replica louis vuitton belts, replica hermes belts, replica hermes belt, Elegant replica louis vuitton belt, Fashion replica louis vuitton belts for men, replica hermes for men.
Hermes belts, Elegant Hermes belt, Fashion Hermes belts for men, Hermes mens belt.
I like! Thank you
I personally have many Louis Vuitton and Gucci wallets, I can afford them, I don’t think I’m being conned and when I take it out of my pocket it looks way better than bringing out a shoddy ‘Bodyglove’ one. Personally and through my company, I donate thousands a year to charity. Now do you think I’m going to listen to anyone on how I spend the money that I earn? —-—-—-—-—— silks-road.com
it probably doesn’t deserve all of the build up that I just gave it, but I suspect that I’ll be writing more about this topic. There’s definitely more to discuss.
Thank you for this nice post
my blog: alpha male | how to run faster
Great stuff, worth reading. Thanks for sharing!
Choose from 4pmp dumps training courses from best private training institutions and third level colleges in hyderabad, India. learnpipe.in includes reviews, special discounts, public course dates, elearning courses, web based courses, and many more training options. testking 70-293|testking 000-977|testking 642-611|testking 642-681|testking HP0-D07|testking JN0-331
Want to buy the hotest white iphone 4 Conversion Kit? www.whiteiphone4.com will be your best online store. Don’t hesitate to buy the charming iphone 4 Conversion Kit!
Mold making is the core business of Intertech (Taiwan). With world level technology, Intertech enjoys a very good reputation for making Injection Mold and Plastic Moldsfor their worldwide customers.
great writing so far on your blog
Shopping for Mens puma speed cat Big Yellow,These matter can be found in many sources. Department supplies may keep them as well as operation shoe locations. Different operation shoed chains will tender a few different shoes from each category of shoe fray. They may hold a line of soccer Puma shoes, operation abrasion and basketball styles. This ideal is a form right shoe that looks great with casual pants. Puma shoes onlinesale Mens Puma Speed Cat Big Yellow Shoes hot sale in Ottawa will give somebody the gamble to attire something that is classy and lively. The panache on the leather and the influence will bestow somebody with an excellent looking Puma shoes. This entry could be tattered with shorts, pants and jeans. Small ankle socks in red or colorless may help to produce a balanced look. A purchaser may find this sort in a footwear store or through an online retailer. In the sell for an open evaluate of the Mens Puma Speed Cat Big Gold Black Shoes? Get the absolute inside scrape and attrition now in our manual to the great puma eminent cat lo.
Hermes belts, Hermes belt, Hermes belts for men, Hermes mens belt, dupont lighter, dupont lighters, st dupont lighter, s.t. dupont lighters.
LV belt, LV belts, LV belts for men, LV Mens belts, louis vuitton mens wallets,gucci mens wallets,hermes mens wallets,prada mens wallets.
Men’s belts, LV men’s belts, Gucci men’s belts, Hermes men’s belts.
I am not certain, but I do know that the access times (insertion, lookup) for vector are defined. Lookup, [], is O 1 (constant time), for example.
Regarding include order, it turns out that using the latest version of CppUTest requires (in the test file), including or at least after any chance of things like , since it overloads global new/delete.
I really like this essay. Thank you for writing it so seriously. I want to recommend it for my friends strongly. iPad to Mac Transfer can help you transfer music, movie, photo, ePub, PDF, Audiobook, Podcast and TV Show from ipad to mac freely.
Would you like to banckup iphone SMS to mac, macBook, macbookPro as .txt files? Now a software iphone SMS to Mac Backup can help you to realize it.
Love this essay!
We are the professional clothes manufacturer and clothes supplier, so we manufacture kinds of custom clothes manufacturer. welcome you to come to our china clothes manufacturer and clothes factory.
hni
Would you like to banckup iphone SMS to mac, macBook, macbookPro as .txt files? Now a software iphone SMS to Mac Backup can help you to realize it.
This is a good post. This post give truly quality information.I’m definitely going to look into it. Really very useful tips are provided here.thank you so much.Keep up the good works. Social Network
Almost any situation--good or bad --is affected by the attitude we bring to. Adversity reveals genius; fortune conceals it. As fruit needs not only sunshine but cold nights and chilling showers to ripen it, so character needs not only joy but trial and difficulty to mellow it. Although the world is full of suffering, it is full also of the overcoming of it. tiffany and co outlet
a Seobaglyak igazán éjszaka érzik elemükben magukat. Szinte ”kétlaki” életet élnek. A Seobaglyak éjszaka sokkal éberebbek, és agresszívabbak, olyannyira, hogy olyankor saját fajtársaikat tartják a legnagyobb ellenségeiknek.
Thanks a lot for sharing this post.
internette görüntülü olarak okey oyunu oyna, gerçek kisilerle tanis, turnuva heyecanini yasa.
ighest quality and cheap belts shop at Hermes belts store.
Highest quality and cheap belts shop at Hermes belt store.
wow.. good blog . thanks
i love this website… got a fine ideas thanks you sir.
thanks for this post sir i lie it…
wonderful blog and informative ..thanks a lot.
wow very nice, i love this website… got a fine idea
like the source code…
What a wonderful article! And are doing well on the whole, but their work also has shortcomings.
Thanks for this post since I am new to C++ and this will help me study.
Australia’s benchmark S&P/ASX200 index rose 3 percent in early trading to 4,214 points, while New Zealand’s benchmark NZX50 was up almost 4 percent by midmorning. In Japan, the Nikkei 225 was up 1.4 percent to 9,073.37 in early trading. Adidas Panda Bear
while New Zealand’s benchmark NZX50 was up almost 4 percent high quality headphones new design headphones
I really enjoy your articles. Very well written. Discount fashion women Coach Lowcut shoes from China for wholesale free shipping,more order,more discount
asda s+dfa+9sd5fd666
asdfsad f+9d68555444
asas fd+-*+s+s+s+s
Abraham Lincoln reportedly said that, given eight hours to chop down a tree, he’d spend six sharpening his axe.
Avertissement consulter cet article représenter l’auteur nike tn , n’a rien à voir avec les chaussures Amoy réseau. Les déclarations d’origine et le papier, les opinions restent juge neutre, ne contient pas le contenu de l’exactitude, la fiabilité ou l’exhaustivité de toute garantie expresse ou implicite. Le lecteur est pour référence seulement, et d’accepter la pleine responsabilité de vos propres basket tn . Nike intelligemment éviter la pression lucratif U. S. entreprise de chaussures Nike (Nike) du premier trimestre des revenus et des prix considérablement augmenté, évitant habilement la pression de marge. La société a déclaré aujourd’hui à propos d’entrer dans les fêtes de Noël requin tn , que ses concurrents dans la même position est très optimiste.
C++ Bowling Kata Result 63 good post91
C++ Bowling Kata Result 64 hoo,good article!!I like the post!180
With more than 20 years of experience, Intertech provides an extensive integrated operational ability from design to production of molds 100% made in Taiwan. Additional to our own mold making factory, we also cooperate with our team vendors to form a very strong working force in Taiwan.
For the overseas market, we work very closely with local representatives in order to take care of the technical communication and after-sales service to our customers. We also participate in the EUROMOLD & FAKUMA exhibitions and meet our customers every year in Europe. By concentrating on mold “niche markets”, we play a very useful mold maker role from the Far East whenever customers want to develop their new projects. We provide services from A to Z to our customers on a very economic cost and effect basis.
With more than 20 years of experience, Intertech provides an extensive integrated operational ability from design to production of molds 100% made in Taiwan. Additional to our own mold making factory, we also cooperate with our team vendors to form a very strong working force in Taiwan.
For the overseas market, we work very closely with local representatives in order to take care of the technical communication and after-sales service to our customers. We also participate in the EUROMOLD & FAKUMA exhibitions and meet our customers every year in Europe. By concentrating on mold “niche markets”, we play a very useful mold maker role from the Far East whenever customers want to develop their new projects. We provide services from A to Z to our customers on a very economic cost and effect basis.
Each famous fashion house, whether it is Hermes or Chanel or Prada etc?
http://www.outfitscosplay.com/cosplay-catalog/tales-of-the-abyss-cosplay Deluxe Tales of The Abyss Cosplay Costumes for Sale.Find your favorite characters and cosplay outfits from all the popular anime and games.