Skip to content

Instantly share code, notes, and snippets.

@Ilchert
Created July 16, 2024 19:32
Show Gist options
  • Save Ilchert/1fd3d49c41f625322ec3ed00a849f08c to your computer and use it in GitHub Desktop.
Save Ilchert/1fd3d49c41f625322ec3ed00a849f08c to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.Linq;
// define BowlingGame Class in a new file
// define Frame Class in a new file
class MainClass
{
static void Main()
{
SomeGame();
SpareGame();
PerfectGame();
//RandomGame();
// code goes here
}
private static void SomeGame() // 119
{
var game = new BowlingGame();
game.Roll(5);
game.Roll(5);
game.Roll(5);
game.Roll(5);
game.Roll(5);
game.Roll(5);
game.Roll(5);
game.Roll(5);
game.Roll(4);
game.Roll(3);
game.Roll(2);
game.Roll(1);
game.Roll(0);
game.Roll(10);
game.Roll(10);
game.Roll(10);
game.Roll(0);
game.Roll(0);
PrintResults(game);
}
private static void SpareGame() //150
{
var game = new BowlingGame();
while (!game.Ended)
game.Roll(5);
PrintResults(game);
}
private static void PerfectGame() // 300
{
var game = new BowlingGame();
while (!game.Ended)
game.Roll(10);
PrintResults(game);
}
private static void RandomGame()
{
var game = new BowlingGame();
while (!game.Ended)
{
var pins = Random.Shared.Next(11);
game.Roll(pins);
Console.WriteLine($"Pins: {pins}");
PrintResults(game);
}
}
private static void PrintResults(BowlingGame game)
{
Console.WriteLine($"Total score: {game.Score()}");
Console.WriteLine($"Scope for all strikes: {game.ScoreStrikes()}");
Console.WriteLine($"Scope for all spares: {game.ScoreSpares()}");
Console.WriteLine();
}
class BowlingGame
{
private const int MaxFrames = 10;
private List<Frame> _frames = new() { new Frame() };
public bool Ended { get; private set; }
public void Roll(int pins)
{
if (pins < 0 || pins > 10)
throw new ArgumentOutOfRangeException();
if (Ended)
throw new InvalidOperationException("Game over");
var lastFrame = _frames[^1];
if (lastFrame.Ended && _frames.Count < MaxFrames)
{
lastFrame = new Frame();
_frames.Add(lastFrame);
}
_frames.ForEach(f => f.Roll(pins));
if (lastFrame.TotalCalculated && _frames.Count == MaxFrames)
Ended = true;
}
public int Score()
{
return _frames.Sum(p => p.Total);
}
public int ScoreStrikes()
{
return _frames.Where(p => p.Type == FrameType.Strike).Sum(p => p.Total);
}
public int ScoreSpares()
{
return _frames.Where(p => p.Type == FrameType.Spare).Sum(p => p.Total);
}
}
internal class Frame
{
public int Total { get; private set; }
public FrameType Type { get; private set; }
public bool Ended { get; private set; }
public bool TotalCalculated { get => _state == FrameState.Completed; }
private FrameState _state;
private const int MaxPins = 10;
public void Roll(int pins)
{
switch (_state)
{
case FrameState.Completed:
return;
case FrameState.FirstRoll:
if (pins == MaxPins)
{
_state = FrameState.StrikeBall1;
Type = FrameType.Strike;
Ended = true;
}
else
{
_state = FrameState.SecondRoll;
}
break;
case FrameState.SecondRoll:
if (pins + Total == MaxPins)
{
_state = FrameState.Spare;
Type = FrameType.Spare;
}
else
{
_state = FrameState.Completed;
}
Ended = true;
break;
case FrameState.Spare:
_state = FrameState.Completed;
break;
case FrameState.StrikeBall1:
_state = FrameState.StrikeBall2;
break;
case FrameState.StrikeBall2:
_state = FrameState.Completed;
break;
default:
throw new ArgumentOutOfRangeException();
}
Total += pins;
}
private enum FrameState
{
FirstRoll,
SecondRoll,
Spare,
StrikeBall1,
StrikeBall2,
Completed
}
}
public enum FrameType
{
Regular,
Spare,
Strike
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment