Initial commit
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using GameOfLife.Entities;
|
||||
|
||||
namespace GameOfLife
|
||||
{
|
||||
public abstract class LifeBase : ILife
|
||||
{
|
||||
public int Generation { get; protected set; }
|
||||
public int Population { get; protected set; }
|
||||
public abstract bool IsCellAlive(Cell cell);
|
||||
public virtual bool IsCellAlive(short x, short y) => IsCellAlive(new Cell(x,y));
|
||||
public bool AllAlive(IEnumerable<Cell> cells) => cells.All(IsCellAlive);
|
||||
public bool AllDead(IEnumerable<Cell> cells) => cells.All(c => !IsCellAlive(c));
|
||||
|
||||
private IReadOnlyList<Tuple<Cell, short>> _neighborhoodField;
|
||||
|
||||
public IReadOnlyList<Tuple<Cell, short>> NeighborhoodField =>
|
||||
// cache values this expensive operation
|
||||
_neighborhoodField ?? (_neighborhoodField = Neighborhood.GetNeighborField(LivingCells).ToList());
|
||||
|
||||
private Pattern _livingCellPattern;
|
||||
|
||||
public Pattern LivingCellPattern =>
|
||||
_livingCellPattern ?? (_livingCellPattern = LivingCells.ToPattern());
|
||||
|
||||
public bool ToggleCell(Cell cell)
|
||||
{
|
||||
var alive = ToggleCell_Internal(cell);
|
||||
Population += alive ? 1 : -1;
|
||||
return alive;
|
||||
}
|
||||
|
||||
protected abstract bool ToggleCell_Internal(Cell cell);
|
||||
|
||||
public void IncrementGeneration()
|
||||
{
|
||||
_neighborhoodField = null;
|
||||
_livingCellPattern = null;
|
||||
Population = IncrementGeneration_Internal();
|
||||
Generation++;
|
||||
}
|
||||
|
||||
protected abstract int IncrementGeneration_Internal();
|
||||
|
||||
public abstract IEnumerable<Cell> LivingCells { get; }
|
||||
|
||||
public static readonly short[,] NeighborOffsets =
|
||||
{
|
||||
{ -1, -1 }, { -1, 0 }, { -1, 1 },
|
||||
{ 0, -1 }, { 0, 1 },
|
||||
{ 1, -1 }, { 1, 0 }, { 1, 1 },
|
||||
};
|
||||
|
||||
public byte GetNeighborCount(short x, short y)
|
||||
{
|
||||
byte numberOfNeighbors = 0;
|
||||
|
||||
for (var i = 0; i < 8; i++)
|
||||
{
|
||||
numberOfNeighbors +=
|
||||
IsCellAlive((short)(x + NeighborOffsets[i,0]), (short)(y + NeighborOffsets[i,1]))
|
||||
? (byte)1
|
||||
: (byte)0;
|
||||
}
|
||||
|
||||
return numberOfNeighbors;
|
||||
}
|
||||
|
||||
protected bool ShouldLive(short x, short y)
|
||||
{
|
||||
var numberOfNeighbors = GetNeighborCount(x, y);
|
||||
|
||||
var isAlive = IsCellAlive(x, y);
|
||||
|
||||
return LifeRule(isAlive, numberOfNeighbors);
|
||||
}
|
||||
|
||||
protected bool LifeRule(bool isAlive, int neighborCount)
|
||||
{
|
||||
switch (isAlive)
|
||||
{
|
||||
case false
|
||||
when neighborCount == 3:
|
||||
case true
|
||||
when neighborCount == 2
|
||||
|| neighborCount == 3:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user