Created
April 30, 2014 11:29
-
-
Save Grepsy/3f4ae1e3f55e2155ef1b to your computer and use it in GitHub Desktop.
Bowling Kata - C#, try 1
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
namespace Katas { | |
class Frame(int index) { | |
public List<int> Rolls = new List<int>(); | |
public int FrameIndex { get; } = index; | |
public bool Completed { | |
get { | |
return (!IsLastFrame && (IsStrike || Rolls.Count == 2)) || | |
(IsLastFrame && (IsSpare || IsStrike) && Rolls.Count == 3) || | |
(IsLastFrame && !(IsSpare || IsStrike) && Rolls.Count == 2); | |
} | |
} | |
public bool IsSpare { | |
get { | |
return Rolls.Count == 2 && Rolls.Sum() == 10; | |
} | |
} | |
public bool IsStrike { | |
get { | |
return (Rolls[0] == 10 && (Rolls.Count == 1 || IsLastFrame)); | |
} | |
} | |
public bool IsLastFrame { | |
get { | |
return FrameIndex == 10; | |
} | |
} | |
public void AddRoll(int roll) { | |
Rolls.Add(roll); | |
} | |
} | |
class Bowling { | |
List<int> rolls = new List<int>(); | |
public void Roll(int pins) { | |
rolls.Add(pins); | |
} | |
public int Score() { | |
var frames = Frames(rolls).ToArray(); | |
int scores = frames.Sum(frame => frame.Rolls.Take(2).Sum()); | |
int spareBonus = frames.Skip(1).Where((_, i) => frames[i].IsSpare).Sum((frame) => frame.Rolls[0]); | |
int strikeBonus = frames.Where(frame => frame.IsStrike) | |
.SelectMany(frame => | |
frames.Skip(frame.FrameIndex) | |
.SelectMany(nextFrame => nextFrame.Rolls) | |
.Take(2)) | |
.Sum(); | |
spareBonus += frames.Where(frame => frame.IsLastFrame && frame.IsSpare && frame.Completed).Sum(frame => frame.Rolls[2]); | |
strikeBonus += frames.Where(frame => frame.IsLastFrame && frame.IsStrike && frame.Completed).Sum(frame => frame.Rolls[2]); | |
return scores + spareBonus + strikeBonus; | |
} | |
private static IEnumerable<Frame> Frames(IEnumerable<int> rolls) { | |
var currentFrameIndex = 1; | |
var currentFrame = new Frame(currentFrameIndex); | |
foreach (var roll in rolls) { | |
currentFrame.AddRoll(roll); | |
if (currentFrame.Completed) { | |
yield return currentFrame; | |
currentFrameIndex++; | |
currentFrame = new Frame(currentFrameIndex); | |
} | |
} | |
} | |
static void Main() { | |
Action<int[], int> test = (rolls, expectedScore) => { | |
var bowling = new Bowling(); | |
foreach (int roll in rolls) | |
bowling.Roll(roll); | |
bool success = bowling.Score() == expectedScore; | |
Console.WriteLine("{0, 5} {1, 3} {2, 3} Rolls: {3}", success, bowling.Score(), expectedScore, String.Join(",", rolls)); | |
}; | |
test(new int[] { 0, 0 }, 0); | |
test(new int[] { 0, 5 }, 5); | |
test(new int[] { 5, 5, 0, 0 }, 10); // Spare w/o bonus points | |
test(new int[] { 5, 5, 5, 0 }, 20); // Spare with bonus points | |
test(new int[] { 10, 0, 0 }, 10); // Strike w/o bonus in both rolls | |
test(new int[] { 10, 5, 0 }, 20); // Strike with bonus in first roll | |
test(new int[] { 10, 0, 5 }, 20); // Strike with bonus in second roll | |
test(new int[] { 10, 5, 5 }, 30); // Strike with bonus in both rolls | |
test(new int[] { 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 }, 300); // Perfect game | |
Console.ReadLine(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment