Skip to content

Instantly share code, notes, and snippets.

@ralfw
Last active October 8, 2018 09:10
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ralfw/991b1bf473e178fed6f9 to your computer and use it in GitHub Desktop.
Save ralfw/991b1bf473e178fed6f9 to your computer and use it in GitHub Desktop.
IODA Architecture for Bowling Game Kata
public class Game {
private int[] rolls = new int[21];
private int currentRoll = 0;
public void roll(int pins) {
rolls[currentRoll++] = pins;
}
public int score() {
var frames = Detect_frames (rolls);
var scores = Score_frames (frames, rolls);
return scores.Sum ();
}
IEnumerable<Frame> Detect_frames(int[] rolls) {
const int MAX_FRAMES = 10;
var fc = new FrameClassifier (rolls);
return Enumerable.Range (1, MAX_FRAMES)
.Select (fc.Classify);
}
IEnumerable<int> Score_frames(IEnumerable<Frame> frames, int[] rolls) {
return frames.Select (f => Score_frame(f, rolls));
}
int Score_frame(Frame frame, int[] rolls) {
switch ((Frame.KindsOfFrame)frame.Kind) {
case Frame.KindsOfFrame.Strike:
case Frame.KindsOfFrame.Spare:
return rolls [frame.RollIndex] + rolls [frame.RollIndex + 1] + rolls [frame.RollIndex + 2];
default:
return rolls [frame.RollIndex] + rolls [frame.RollIndex + 1];
}
}
class Frame {
public enum KindsOfFrame {
Regular,
Spare,
Strike
}
public int FrameNr;
public KindsOfFrame Kind;
public int RollIndex;
}
class FrameClassifier {
int[] rolls;
int rollIndex = 0;
public FrameClassifier(int[] rolls) {
this.rolls = rolls;
}
public Frame Classify(int frameNumber) {
const int MAX_FRAME_PINS = 10;
dynamic frame = new Frame{ FrameNr = frameNumber, Kind = Frame.KindsOfFrame.Regular, RollIndex = rollIndex};
if (rolls [rollIndex] == MAX_FRAME_PINS) {
frame.Kind = Frame.KindsOfFrame.Strike;
rollIndex += 1;
} else {
if (rolls [rollIndex] + rolls [rollIndex + 1] == MAX_FRAME_PINS)
frame.Kind = Frame.KindsOfFrame.Spare;
rollIndex += 2;
}
return frame;
}
}
}
public class Game {
private int[] rolls = new int[21];
private int currentRoll = 0;
public void roll(int pins) {
rolls[currentRoll++] = pins;
}
public int score() {
var frames = Detect_frames (rolls);
var scores = Score_frames (frames, rolls);
return scores.Sum ();
}
IEnumerable<Frame> Detect_frames(int[] rolls) {
const int MAX_FRAMES = 10;
return Classify_frames (new List<Frame>(), rolls, MAX_FRAMES).Frames;
}
dynamic Classify_frames(List<Frame> frames, int[] rolls, int frameNumber) {
dynamic classifications = null;
if (frameNumber > 1) classifications = Classify_frames (frames, rolls, frameNumber - 1);
dynamic classification = Classify_frame (frameNumber, rolls, classifications == null ? 0 : classifications.NextRollIndex);
frames.Add (classification.Frame);
return new { Frames = frames, NextRollIndex = classification.NextRollIndex };
}
dynamic Classify_frame(int frameNumber, int[] rolls, int rollIndex) {
const int MAX_FRAME_PINS = 10;
dynamic frame = new Frame{ FrameNr = frameNumber, Kind = Frame.KindsOfFrame.Regular, RollIndex = rollIndex};
if (rolls [rollIndex] == MAX_FRAME_PINS) {
frame.Kind = Frame.KindsOfFrame.Strike;
rollIndex += 1;
} else {
if (rolls [rollIndex] + rolls [rollIndex + 1] == MAX_FRAME_PINS)
frame.Kind = Frame.KindsOfFrame.Spare;
rollIndex += 2;
}
return new {Frame = frame, NextRollIndex = rollIndex};
}
IEnumerable<int> Score_frames(IEnumerable<Frame> frames, int[] rolls) {
return frames.Select (f => Score_frame(f, rolls));
}
int Score_frame(Frame frame, int[] rolls) {
switch ((Frame.KindsOfFrame)frame.Kind) {
case Frame.KindsOfFrame.Strike:
case Frame.KindsOfFrame.Spare:
return rolls [frame.RollIndex] + rolls [frame.RollIndex + 1] + rolls [frame.RollIndex + 2];
default:
return rolls [frame.RollIndex] + rolls [frame.RollIndex + 1];
}
}
class Frame {
public enum KindsOfFrame {
Regular,
Spare,
Strike
}
public int FrameNr;
public KindsOfFrame Kind;
public int RollIndex;
}
}
// adapted from: http://butunclebob.com/files/downloads/Bowling%20Game%20Kata.ppt
public class Game {
private int[] rolls = new int[21];
private int currentRoll = 0;
public void roll(int pins) {
rolls[currentRoll++] = pins;
}
public int score() {
int score = 0;
int frameIndex = 0;
for (int frame = 0; frame < 10; frame++) {
if (isStrike(frameIndex)) {
score += 10 + strikeBonus(frameIndex);
frameIndex++;
} else if (isSpare(frameIndex)) {
score += 10 + spareBonus(frameIndex);
frameIndex += 2;
} else {
score += sumOfBallsInFrame(frameIndex);
frameIndex += 2;
}
}
return score;
}
private bool isStrike(int frameIndex) {
return rolls[frameIndex] == 10;
}
private int sumOfBallsInFrame(int frameIndex) {
return rolls[frameIndex] + rolls[frameIndex+1];
}
private int spareBonus(int frameIndex) {
return rolls[frameIndex+2];
}
private int strikeBonus(int frameIndex) {
return rolls[frameIndex+1] + rolls[frameIndex+2];
}
private bool isSpare(int frameIndex) {
return rolls[frameIndex]+rolls[frameIndex+1] == 10;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment