PDA

View Full Version : C++ Bowling Score for class




slooksterPSV
Jan 21, 2007, 11:06 PM
We have to make a program that calculates the score of a bowling game, here's my code, but it isn't working right here's an input that was given to us along with the scores, my code is at the bottom:
1----2----3----4----5----6----7----8----9----10
9\__-\___X___X__62__7\__8\___X___9-__9\X
10--30---56---74---82--100-120-139-148-168


//Frame.h
#ifndef __FRAME_H_
#define __FRAME_H_

#include <iostream>
using namespace std;

struct Score
{
int amount;
char symbol;
};

Score score[16] = {
{0, '0'},
{1, '1'},
{2, '2'},
{3, '3'},
{4, '4'},
{5, '5'},
{6, '6'},
{7, '7'},
{8, '8'},
{9, '9'},
{10, 'X'},
{10, 'T'},
{0, 'F'},
{0, 'G'},
{0, '-'},
{10, '\\'} };

class Frame
{
private:
int numBowls;
char bowl[3];
int scoreBowl;
public:
Frame(int nBowls) { numBowls = nBowls; scoreBowl = 0; };
void calculateScore(Frame aFrame, Frame bFrame);
void setBowls(char, char, char);
int getScore();
};

void Frame::calculateScore(Frame aFrame, Frame bFrame)
{
Frame tempFrame = Frame(2);
tempFrame.setBowls('0','0', '0');
int x = 0;
int y = 0;
for(x = 0; x <= 15; x++)
{
for(y = 0; y < numBowls; y++)
{
if((bowl[y] == score[x].symbol) && (bowl[y+1] != '\\'))
{
scoreBowl = score[x].amount;
}else if(bowl[y+1] == '\\')
{
scoreBowl = 10;
aFrame.calculateScore(tempFrame, tempFrame);
scoreBowl += aFrame.getScore();
// cout << scoreBowl << "\t\t";
y = numBowls;
x = 15;
}
else if((bowl[y] == score[x].symbol) && (score[x].symbol == 'X') )
{
aFrame.calculateScore(tempFrame, tempFrame);
bFrame.calculateScore(tempFrame, tempFrame);
//cout << bFrame.bowl << endl;
scoreBowl += aFrame.getScore();
scoreBowl += bFrame.getScore();
y = numBowls;
x = 15;
}
else if((bowl[y] == score[x].symbol) && (score[x].symbol == '\\'))
{
aFrame.calculateScore(tempFrame, tempFrame);
scoreBowl += aFrame.getScore();
y = numBowls;
x = 15;
}
}
}
}

void Frame::setBowls(char a, char b, char c)
{
if(numBowls == 2)
{
bowl[0] = a;
bowl[1] = b;
}
if(numBowls == 3)
{
bowl[0] = a;
bowl[1] = b;
bowl[2] = c;
}
}

int Frame::getScore()
{
return scoreBowl;
}

#endif



//main.cpp
#include <iostream>
#include "frame.h"

using namespace std;

int main (int argc, char * const argv[]) {
char bowling[22];
int score = 0;
cout << "Please enter bowling scores without spaces in the form of 0-9, T, F, X, \, -: ";
cin >> bowling;
Frame frm[9] = Frame(2);
int y = 0;
for(int x = 0; x < 22; x++)
{
if(y < 9){
for(y = 0; y < 10; y++)
{
if(bowling[x] == 'X')
{
frm[y].setBowls(bowling[x], '0', '0');
//cout << bowling[x]<< "\t" << bowling[x+1] << "\t" << y << endl;
x += 1;
}else
{
//cout << bowling[x] << "\t" << bowling[x+1] << "\t" << y << endl;
frm[y].setBowls(bowling[x], bowling[x+1], '0');
x += 1;
}
}
}
}
// frm[0].calculateScore(frm[1], frm[2]);
for(int z = 0; z < 9; z++)
{
if(z <= 6)
{
frm[z].calculateScore(frm[z+1], frm[z+2]);
}else if(z == 7)
{
frm[z].calculateScore(frm[z+1], NULL);
}else
{
frm[z].calculateScore(NULL, NULL);
}
}
// frm[1].calculateScore(frm[2], NULL);
// frm[2].calculateScore(NULL, NULL);
for(int a = 0; a < 9; a++)
{
score += frm[a].getScore();
cout << score << "\t";
}
return 0;
}


What do I need to do to fix it or that?

EDIT: No I don't have the 10th frame setup yet, I wanna get these 9 frames working, numbers 0 to 9 work but X \ - don't



scan
Jan 23, 2007, 09:28 AM
First off, I would like to say I'm no C++ expert but I can give you some suggestions, but I'm still trying to decipher your code. In the meantime, try commenting your code so people reading it know what are your intentions with a block or what a method does.

You should also probably shorten the main and leave the work to be done in the object's methods or functions if you want to go about this problem in a more procedural way. Your main coudl probably looks something like:

main():
contruct bowlingGameObject bgo
bgo.getsInput(); //populars the scores of the game into a 2d array (maybe?)
bgo.calcScore(); //calculates the final score

thats pretty much it. As you can see your main is really messy and shouldn't do that. You are straying from the OOP principal, which you can get away with, but thats not good code.

if i get the time i'll try to do this in java but i'm at work right now.

scan
Jan 23, 2007, 02:46 PM
Ok just did this after my lunch break. It is in Java but I'm sure you can convert it. Don't mind the mess. I also just hard coded the scores. Cheers.

class BowlingGame:

import java.util.ArrayList;

public class BowlingGame {
//variables
//9\__-\___X___X__62__7\__8\___X___9-__9\X
//10--30---56---74---82--100-120-139-148-168
private ArrayList gameFrame = new ArrayList();
private int score = 0;

public BowlingGame()
{ //index; frame points
gameFrame.add(new Frame('9','/')); //0; 10
gameFrame.add(new Frame('-','/')); //1; 20
gameFrame.add(new Frame('X',' ')); //2; 26
gameFrame.add(new Frame('X',' ')); //3; 18
gameFrame.add(new Frame('6','2')); //4; 8
gameFrame.add(new Frame('7','/')); //5; 18
gameFrame.add(new Frame('8','/')); //6; 20
gameFrame.add(new Frame('X',' ')); //7; 19
gameFrame.add(new Frame('9','-')); //8; 9
gameFrame.add(new TenthFrame('9','/','X')); //9; 20
}


public int calcScore()
{
Frame nextFrame;

for (int i=0; i < 10; i++)
{
//if last frame
if(i==9)
{
System.out.println("Frame #" + (i+1) + "\n"
+ ((TenthFrame)gameFrame.get(i)).getBall1()
+ ", " + ((TenthFrame)gameFrame.get(i)).getBall2()
+ ", " + ((TenthFrame)gameFrame.get(i)).getBall3());
score += calcTenthFrame((TenthFrame)gameFrame.get(i));
System.out.println("running score is " + score);
}
else
{
System.out.println("Frame #" + (i+1) + "\n"
+ ((Frame)gameFrame.get(i)).getBall1()
+ ", " + ((Frame)gameFrame.get(i)).getBall2());

if( ((Frame)gameFrame.get(i)).isSpare() )
{
nextFrame = (Frame)gameFrame.get(i+1);
score += 10 + intVal(nextFrame.getBall1());
}
//if next ball is a strike, add the next frame's first ball.
else if( ((Frame)gameFrame.get(i)).isStrike() && (i+1)!=9)
{
nextFrame = (Frame)gameFrame.get(i+1);
score += 10;
if (nextFrame.getBall1() == 'X')
{
score+=10;
nextFrame = (Frame)gameFrame.get(i+2);
score+=intVal(nextFrame.getBall1());
}
else
score += calcFrameScore(nextFrame);
}
else if( ((Frame)gameFrame.get(i)).isStrike() && (i+1)==9)
{
nextFrame = (TenthFrame)gameFrame.get(i+1);
score += 10;
if (nextFrame.getBall1() == 'X')
{
score += 10 + intVal(nextFrame.getBall2());
}
score += intVal(nextFrame.getBall1()) + intVal(nextFrame.getBall2());
}
else
score += calcFrameScore((Frame)gameFrame.get(i));

System.out.println("running score is " + score);
}

}
return score;
}

public int intVal(char a)
{
switch(a)
{
case '1': return 1;
case '2': return 2;
case '3': return 3;
case '4': return 4;
case '5': return 5;
case '6': return 6;
case '7': return 7;
case '8': return 8;
case '9': return 9;
case 'X':
case '/':
return 10;
default: return 0;
}
}

public int calcTenthFrame(TenthFrame frame)
{
if (frame.getBall2() == '/')
return 10 + intVal(frame.getBall3());
else if (frame.getBall3() == '/')
return 10 + intVal(frame.getBall1());
else
return intVal(frame.getBall1()) + intVal(frame.getBall2()) + intVal(frame.getBall3());
}
public int calcFrameScore(Frame frame)
{
return intVal(frame.getBall1()) + intVal(frame.getBall2());
}

}



Frame class:

public class Frame {

private char ball1;
private char ball2;


public Frame(char ball1, char ball2)
{
this.ball1=ball1;
this.ball2=ball2;
}
public char getBall1()
{
return ball1;
}

public char getBall2()
{
return ball2;
}
public boolean isStrike()
{
return this.getBall1() == 'X';
}
public boolean isSpare()
{
return (this.getBall2() == '/' || this.getBall2() == '/');
}

}


TenthFrame class


public class TenthFrame extends Frame {
private char ball3;

public TenthFrame(char ball1, char ball2, char ball3)
{
super(ball1,ball2);
this.ball3=ball3;
}

public char getBall3()
{
return ball3;
}


}


Main-Class: GameTest class


public class GameTest {

public static void main(String[] args) {
BowlingGame bg = new BowlingGame();
System.out.println("Your score is " + bg.calcScore());

}

}

Heath
Jan 23, 2007, 04:36 PM
You might want to have a look here to get a good idea of how the pros do this sort of thing.
Bowling Kata (http://www.butunclebob.com/ArticleS.UncleBob.TheBowlingGameKata)

toddburch
Jan 27, 2007, 12:36 AM
Ruby. Works.


# Todd Burch Jan 27, 2007 www.smustard.com

class Frame ;

attr_accessor :strike, :spare, :ball ;

def initialize(fnumber) ;
@ball = Array.new(2,0) ; # allow a frame to keep 2 scores. Init to zero.
@spare = false ; # assume no spare
@strike = false ; # assume no strike
#puts "Frame # = #{fnumber}; scores=#{$scores}" ; # diagnostic
return if (fnumber==11 and $scores.length==0) ; # there is no 3rd ball in the tenth

# BALL NUMBER 1

val = $scores.shift ; # remove the first character
#puts "...BALL 1=>#{val}<" ; # diagnostic
@ball[0] = case val ; # through the case statement, assign a value to the score.
when "X" then @strike = true ; 10 ;
when "-" then 0 ;
else val.to_i ;
end ;

return if @strike ; # if a strike was thrown, we're done with this frame.
return if $scores.length==0 ; # if not more scores, we're done.

# BALL NUMBER 2

val = $scores.shift # get next character
#puts "...BALL 2=>#{val}<" ; # diagnostic
@ball[1] = case val ; # through the case, assign a value to the score.
when "X" then 10 ; # can only occur in the 10th frame.
when "\\" then @spare = true ; (10 - @ball[0].to_i) ; # make both throws add up to 10
when "-" then 0 ; # gutter ball baby. Get the bumpers.
else val.to_i ;
end ;
end ;

def total
return self.ball[0] + self.ball[1] ; # add both throws together for this frame.
end ; # def total
end ; # class Frame ;

class Game ;
attr_accessor :frame, :score
@@frames = 12 ; # for ease of calculations, pretend there are 12 frames, not ten.
def initialize ; # called for a "new"
@score = 0 ; # cumulative score for the game.
@frame = Array.new ; # array to keep track of every frames rolls
frame_number = 1 ;
@@frames.times do ; # init the frames array.
@frame.push(Frame.new(frame_number)) ;
frame_number += 1 ;
end ; # @frames.times
end ; # initialize

def calc(frames) # add up the scores for however many frames.
self.frame.each_index {|f|
break if f>([frames,9].min) ; # only count 10 frames
j = f + 1 ; # next frame index
k = f + 2 ; # frame + 2 index
if self.frame[f].strike then # if a strike was thrown in this frame...
if self.frame[j].strike then # and the next frame was a strike too...
@score += (self.frame[f].total + self.frame[j].total + self.frame[k].ball[0]) ; # add next 2 frame's balls
else @score += (self.frame[f].total + self.frame[j].total) ; # add next frame's 2 balls
end ;
elsif self.frame[f].spare then # otherwise, if a spare thrown?
@score += (self.frame[j].total + self.frame[j].ball[0]) ; # add next frame's 1st ball
else @score += self.frame[f].total ; # just add this frame's balls
end ; # if strike
}
@score ; # return the score
end ; # def calc
end ; # class Game

DATA.each_line do |d| # read the data at the "__END__" of the file.
$scores = d.strip.split(//) ; # turn the string into an array
g = Game.new ; # new up a Game class and all it's frames.
puts "The game marking was #{d}" ; # report the score keeper's notes.
i = 0 ;
g.frame.each {|f| # uncomment out the "puts" for a verbose answer.
#puts "frame:#{i+1} balls=#{f.ball[0]},#{f.ball[1]}; spare=#{f.spare}, strike=#{f.strike}: score=#{g.calc(i)}" ;
i += 1 ;
g.score = 0 ; # reset for each iteration
}
puts "The score is #{g.calc(10)}" ; # Give the total score, count 10 frames worth of scores.
end ; # DATA loop

__END__
11223344556677889900
11121314151617181911
XXXXXXXXXXXX
--------------------
1\2\3\4\5\6\7\8\9\0\9
-\-\-\-\-\-\-\-\-\-\X
9\-\XX627\8\X9-9\X