( Java Assignment ) Write a program that simulates and scores a game of bowling.
ID: 3869985 • Letter: #
Question
( Java Assignment )
Write a program that simulates and scores a game of bowling. As background information, here is an explanation of terminology and scoring.
Your game will need to keep score for at least one player, multiple players are allowed. 10 frames for each player, and if the final frame is a strike or spare they roll the 11th frame.
(Instructions)
1.No BlueJ, use Netbeans, Eclipse or another approved IDE.
2.Create a class named Bowling that will manage the game....my public static void main was in my bowling, I set things up in constructor then called play() and that method handled the 10 frames, including calling methods to do things such as print the formatted output. I also used a Frame class. You can use more than one .java file
3.Create a Bowling class such that when the main method of the Driver class is run, HERE IS THE FORMATTED OUTPUT. It is a screen capture of me running my program five times. Note: match the output format exactly! You only need to run it once, match one of the lines....with your random scores that come up, not mine.
4.Your bowling game should knock down pins randomly, use a random number generator.......but just like in real bowling (no I do not bowl) higher numbers should be weighted more so you roll more 7s than 2s for instance. 0, 1, 2, 3, 4, 5 should all have a weight of 1. 6 should have a weight of 2. 7 and 10 should have a weight of 3, 8 and 9 should have a weight of 4 for first roll only. Second roll should be weighted all equal but you should only knock down how many of the 10 pins are left after the first roll. Weights make the game more fun to play.
5.Any spare or strike (anytime you get all 10 pins down on roll1 or roll2) you should do the scoring properly adding to the previous frame.
6.10th frame should be done properly. Handling spares and strikes in the 10th frame properly.
7.You should set your game up to hold on to all frames first and second ball scores and each frame score.....it will make it easier in the long run.
8.Feel free to add two player games. Put in some skill by a player instead of just randomness. Still needs to be able to do random numbers also.
9.import java.util.random and look up the Random class to use random number generation.
10.Test without random numbers, force certain scores to happen with a test data set to make sure your game is working properly. All strikes equals a perfect game of 300....test that.
(Hints and Assumptions)
1.Design your solution out on paper before you start coding.
2.Design first. Translate into a programming language (Java) second.
3.When the final frame contains a strike or spare, the frame needs to be printed differently. Please study the output transcript above carefully to see how.
Update: I put my play() call in a for loop that called it five times and gave the following output: You need to match one line, or one 10 frame game of this screen capture with your random scores (don't copy my scores down, the game should run dynamically)
Bowing NetBeans IDE 82 16 38 63 72 108 19 71 95 104 113 4 x 20 36 79 93 118 19 45 73 81 90 110 140 -Frame 1--Frame 2-Frame 3Frame -Frame 5Frame 6-Frame 7-Frame 8Frame 9Frame 10 16 30 43 49Explanation / Answer
MatchFactory.java
public final class MatchFactory {
private MatchFactory(){};
public static BowlingGame createMatch() {
return new BowlingGameScoreBoard();
}
}
BowlingGame.java
public interface BowlingGame {
/**
* Keeps track of pins knocked over
* @param noOfPins knocked over per frame
* @exception {@link au.com.dius.BowlingGameScoreBoard.BowlingException}
*/
public void roll(int noOfPins);
/**
*
* @return score of current frame only
*/
public int score();
}
BowlingGameScoreBoard.java
public final class BowlingGameScoreBoard implements BowlingGame {
private final List<Frame> frames;
private static final int MAX_FRAMES = 10;
private static final int MAX_PINS = 10;
private static final int MAX_ATTEMPTS_PER_FRAME = 2;
private int frameCounter = 0;
private int strikeCounter = 0;
private static final int ALL_STRIKE_SCORE = 300;
/**
* setup the game, ie all {@link BowlingGameScoreBoard#MAX_FRAMES} frames
*/
public BowlingGameScoreBoard() {
frames = new ArrayList<Frame>(MAX_FRAMES);
for (int i = 0; i < MAX_FRAMES; i++) {
frames.add(new Frame());
}
}
@Override
public void roll(int noOfPins) {
if (noOfPins > MAX_PINS) {
throw new BowlingException("illegal argument " + noOfPins);
}
Frame frame = getFrame();
if (frame == null) {
throw new BowlingException("all attempts exhausted - start new game");
}
frame.setScore(noOfPins);
if (isBonusFrame()) {
Frame prev = getPreviousFrame();
// restrict to one attempt, when last frame was spare
if (prev.isSpare()) {
frame.limitToOneAttempt();
}
}
}
/**
* returns a frame and moves to next frame if current has used up attempts
* @return {@link au.com.dius.BowlingGameScoreBoard.Frame}
*/
private Frame getFrame(){
Frame frame = getCurrentFrame();
if (frame.isDone()) {
// new bonus frame
if(isLastFrame() && (frame.isSpare() || frame.isStrike())) {
Frame bonus = new Frame();
frames.add(bonus);
frameCounter++;
return bonus;
}
frameCounter++;
if (frameCounter == MAX_FRAMES || isBonusFrame()) {
return null;
}
frame = getCurrentFrame();
}
return frame;
}
@Override
public int score() {
int score;
// first frame
if (frameCounter == 0) {
Frame curr = getCurrentFrame();
return curr.score();
} else {
// score 300, strikes for all frames
if (isLastFrame() && isAllStrikes()) {
return ALL_STRIKE_SCORE;
}
Frame curr = getCurrentFrame();
Frame prev = getPreviousFrame();
// only add previous last frame to current score
if (isBonusFrame()) {
return prev.score() + curr.score();
}
score = curr.score();
if(prev.isSpare()) {
score += (prev.score() + curr.getFirstScore());
}
if(prev.isStrike()) {
score += (prev.score() + curr.getFirstScore() + curr.getSecondScore());
}
}
return score;
}
private Frame getPreviousFrame() {
return frames.get(frameCounter-1);
}
private Frame getCurrentFrame() {
return frames.get(frameCounter);
}
private boolean isAllStrikes() {
return strikeCounter == MAX_FRAMES ;
}
private boolean isBonusFrame() {
return frames.size() > MAX_FRAMES;
}
private boolean isLastFrame() {
return frameCounter == MAX_FRAMES - 1;
}
/**
* This nested class encapsulates the concept of a frame
* and manages score and attempts allowed for each frame
*/
private class Frame {
private int[] scores = new int[MAX_ATTEMPTS_PER_FRAME];
private int noOfPins = 10;
private int noAttempts = 0;
private boolean isStrike = false;
private boolean isSpare() {
return noOfPins == 0 && noAttempts == MAX_ATTEMPTS_PER_FRAME && !isStrike;
}
private boolean isStrike() {
return noOfPins == 0 && noAttempts == MAX_ATTEMPTS_PER_FRAME && isStrike;
}
private boolean isDone () {
return noAttempts == MAX_ATTEMPTS_PER_FRAME;
}
private void setScore(int score) {
scores[noAttempts++] = score;
noOfPins -= score; // keep track of remaining pins/frame
if (score == MAX_PINS) {
isStrike = true;
strikeCounter++;
}
}
private void limitToOneAttempt(){
scores[1] = 0;
noAttempts++;
}
private int score() { return scores[0] + scores[1];}
private int getFirstScore() {
return scores[0];
}
private int getSecondScore() {
return scores[1];
}
}
/**
* Represents an exception for the bowling game
*/
public class BowlingException extends RuntimeException {
BowlingException(String message) {
super(message);
}
}
}
BowlingGameTest.java
@RunWith(JUnit4.class)
public class BowlingGameTest {
private BowlingGame game;
private static final int MAX_ATTEMPTS = 20;
@Before
public void setUp() {
game = MatchFactory.createMatch();
}
@Test
public void testScoreNoSpareOrStrike() {
game.roll(4);
game.roll(4);
int score = game.score();
Assert.assertEquals(8, score);
}
@Test
public void testSpare() {
game.roll(4);
game.roll(6);
int score = game.score();
Assert.assertEquals(10, score);
game.roll(5);
game.roll(0);
score = game.score();
Assert.assertEquals(20, score);
}
@Test
public void testStrikeOnSecondAttempt() {
game.roll(0);
game.roll(10);
int score = game.score();
Assert.assertEquals(10, score);
game.roll(5);
game.roll(4);
score = game.score();
Assert.assertEquals(28, score);
}
@Test
public void testStrikeOnFirstAttempt() {
game.roll(10);
game.roll(0);
int score = game.score();
Assert.assertEquals(10, score);
game.roll(5);
game.roll(5);
score = game.score();
Assert.assertEquals(30, score);
}
@Test
public void testStrikeEveryRoll() {
for (int i = 0; i < 10 ; i++) {
game.roll(10);
game.roll(0);
}
int score = game.score();
Assert.assertEquals(300, score);
}
@Test
public void testLastFrameSpare() {
for (int i = 0; i < 10 ; i++) {
game.roll(5);
game.roll(5);
}
game.roll(5);
int score = game.score();
Assert.assertEquals(15, score);
}
@Test
public void testLastFrameStrike() {
for (int i = 0; i < 10 ; i++) {
game.roll(10);
game.roll(0);
}
game.roll(3);
game.roll(4);
int score = game.score();
Assert.assertEquals(17, score);
}
@Test(expected = BowlingGameScoreBoard.BowlingException.class)
public void testLastFrameNoStrike() {
for (int i = 0; i < 10 ; i++) {
game.roll(3);
game.roll(5);
}
// this wont happen as last frame wasnt strike/spare
game.roll(3);
game.roll(4);
}
/**
* Exception is generated if try and go beyond 10 frames / match
*/
@Test(expected = BowlingGameScoreBoard.BowlingException.class)
public void testPlayMoreThanAllFrames() {
for (int i = 0; i <= MAX_ATTEMPTS ; i++) {
game.roll(i/10);
}
}
/**
* This tests an illegal argument , ie cant pass more than 10 pins to
* knock down
*
* I'am using custom exception here instead of Java's {@link java.lang.IllegalArgumentException}
*/
@Test(expected = BowlingGameScoreBoard.BowlingException.class)
public void testIllegalBowlException() {
game.roll(200);
}
}
Related Questions
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.