// Copyright (C) 2003-2009 by Object Mentor, Inc. All rights reserved. // Released under the terms of the CPL Common Public License version 1.0. package fitnesse.slim.test; import java.util.Arrays; import java.util.List; public class Bowling { private Game g; @SuppressWarnings("unchecked") public List<?> doTable(List<List<String>> table) { g = new Game(); List<?> rollResults = Arrays.asList("", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""); List<String> scoreResults = Arrays.asList("", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", ""); rollBalls(table); evaluateScores(g, table.get(1), scoreResults); return Arrays.asList(rollResults, scoreResults); } private void evaluateScores(Game g, List<String> object, List<String> scoreResults) { for (int frame = 0; frame < 10; frame++) { int actualScore = g.score(frame + 1); int expectedScore = Integer.parseInt(object.get(frameCoordinate(frame))); if (expectedScore == actualScore) scoreResults.set(frameCoordinate(frame), "pass"); else scoreResults.set(frameCoordinate(frame), String.format("Was:%d, expected:%s.", actualScore, expectedScore)); } } private int frameCoordinate(int frame) { return frame < 9 ? frame * 2 + 1 : frame * 2 + 2; } private void rollBalls(List<List<String>> table) { List<String> rollRow = table.get(0); for (int frame = 0; frame < 10; frame++) { String firstRoll = rollRow.get(frame * 2); String secondRoll = rollRow.get(frame * 2 + 1); rollFrame(firstRoll, secondRoll); } } private void rollFrame(String firstRoll, String secondRoll) { if (firstRoll.equalsIgnoreCase("X")) g.roll(10); else { int firstRollInt = parseFirstRoll(firstRoll); parseSecondRoll(secondRoll, firstRollInt); } } private void parseSecondRoll(String secondRoll, int firstRollInt) { if (secondRoll.equals("/")) g.roll(10 - firstRollInt); else if (secondRoll.equals("-")) g.roll(0); else g.roll(Integer.parseInt(secondRoll)); } private int parseFirstRoll(String firstRoll) { int firstRollInt = 0; if (firstRoll.equals("-")) g.roll(0); else { firstRollInt = Integer.parseInt(firstRoll); g.roll(firstRollInt); } return firstRollInt; } private class Game { int[] rolls = new int[21]; int currentRoll = 0; public void roll(int pins) { rolls[currentRoll++] = pins; } public int score(int frame) { return new Scorer(frame).score(); } private class Scorer { private int frame; private int score; private int firstBall; public Scorer(int frame) { this.frame = frame; score = 0; firstBall = 0; } public int score() { for (int f = 0; f < frame; f++) scoreFrame(); return score; } private void scoreFrame() { if (isStrike(firstBall)) { scoreStrike(); } else if (isSpare(firstBall)) { scoreSpare(); } else { scoreNoMark(); } } private void scoreNoMark() { score += twoBallsInFrame(firstBall); firstBall += 2; } private void scoreSpare() { score += 10 + nextBallForSpare(firstBall); firstBall += 2; } private void scoreStrike() { score += 10 + nextTwoBallsForStrike(firstBall); firstBall += 1; } private int twoBallsInFrame(int firstBall) { return rolls[firstBall] + rolls[firstBall + 1]; } private int nextBallForSpare(int firstBall) { return rolls[firstBall + 2]; } private int nextTwoBallsForStrike(int firstBall) { return rolls[firstBall + 1] + rolls[firstBall + 2]; } private boolean isSpare(int firstBall) { return rolls[firstBall] + rolls[firstBall + 1] == 10; } private boolean isStrike(int firstBall) { return rolls[firstBall] == 10; } } } }