init
This commit is contained in:
142
src/Board.cs
Normal file
142
src/Board.cs
Normal file
@@ -0,0 +1,142 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace InverseOfLife;
|
||||
|
||||
public class Board
|
||||
{
|
||||
[SetsRequiredMembers]
|
||||
public Board(int w, int h, bool qx = false, bool qy = false, bool useTracer = false)
|
||||
{
|
||||
Width = w;
|
||||
Height = h;
|
||||
QuotientX = qx;
|
||||
QuotientY = qy;
|
||||
Lives = new();
|
||||
if (useTracer)
|
||||
Tracer = new CellTracer();
|
||||
}
|
||||
|
||||
public required int Width { get; init; }
|
||||
public required int Height { get; init; }
|
||||
public required bool QuotientX { get; init; }
|
||||
public required bool QuotientY { get; init; }
|
||||
public HashSet<(int, int)> Lives { get; init; }
|
||||
public CellTracer? Tracer { get; init; }
|
||||
|
||||
public void Toggle(int x, int y, bool initialConfig=false)
|
||||
{
|
||||
bool added = Lives.Add((x, y));
|
||||
if (!added)
|
||||
{
|
||||
Lives.Remove((x, y));
|
||||
if (initialConfig && Tracer is not null)
|
||||
Tracer.Contribution.Remove((x, y));
|
||||
}
|
||||
else if (initialConfig && Tracer is not null)
|
||||
{
|
||||
Tracer.Contribution[(x, y)] = new Dictionary<(int, int), double>
|
||||
{
|
||||
{ (x, y), 1d }
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public void Toggle((int x, int y) cell, bool initialConfig = false) => Toggle(cell.x, cell.y, initialConfig);
|
||||
|
||||
public void Evaluate(int steps)
|
||||
{
|
||||
for(int i = 0; i< steps; i++)
|
||||
Evaluate();
|
||||
}
|
||||
|
||||
public void Evaluate()
|
||||
{
|
||||
Dictionary<(int, int), int> neighbourCount = new();
|
||||
foreach ((int x, int y) in Lives)
|
||||
{
|
||||
if (!neighbourCount.ContainsKey((x, y)))
|
||||
neighbourCount[(x, y)] = 0;
|
||||
Populate(x, y, neighbourCount);
|
||||
}
|
||||
|
||||
foreach ((int x, int y) in neighbourCount.Keys)
|
||||
{
|
||||
if (Lives.Contains((x, y)))
|
||||
{
|
||||
if (neighbourCount[(x, y)] != 2 && neighbourCount[(x, y)] != 3)
|
||||
{
|
||||
Lives.Remove((x, y));
|
||||
if (Tracer is not null)
|
||||
Tracer.DeferredRemove((x, y));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (neighbourCount[(x, y)] == 3)
|
||||
{
|
||||
Lives.Add((x, y));
|
||||
if (Tracer is not null)
|
||||
Tracer.DeferredAdd((x, y));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Tracer is not null)
|
||||
Tracer.BatchProcess();
|
||||
}
|
||||
|
||||
public void Populate(int x, int y, Dictionary<(int, int), int> count)
|
||||
{
|
||||
for (int dx = -1; dx <= 1; dx++)
|
||||
{
|
||||
for (int dy = -1; dy <= 1; dy++)
|
||||
{
|
||||
if (dx == 0 && dy == 0)
|
||||
continue;
|
||||
int nx = QuotientX ? (x + dx + Width) % Width : x + dx;
|
||||
int ny = QuotientY ? (y + dy + Height) % Height : y + dy;
|
||||
if(nx >= Width || nx < 0)
|
||||
continue;
|
||||
if(ny >= Height || ny < 0)
|
||||
continue;
|
||||
if (!count.ContainsKey((nx, ny)))
|
||||
count[(nx, ny)] = 0;
|
||||
count[(nx, ny)] += 1;
|
||||
if (Tracer is not null)
|
||||
{
|
||||
if (!Tracer.Parents.ContainsKey((nx, ny)))
|
||||
Tracer.Parents[(nx, ny)] = new HashSet<(int, int)>();
|
||||
Tracer.Parents[(nx, ny)].Add((x, y));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
|
||||
var builder = new System.Text.StringBuilder();
|
||||
|
||||
for (int y = 0; y < Height; y++)
|
||||
{
|
||||
for (int x = 0; x < Width; x++)
|
||||
builder.Append(Lives.Contains((x, y)) ? 'o' : ' ');
|
||||
|
||||
builder.AppendLine();
|
||||
}
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
|
||||
public void Play(int generations, int delay = 200)
|
||||
{
|
||||
for (int i = 0; i < generations; i++)
|
||||
{
|
||||
Console.Clear();
|
||||
Console.WriteLine(ToString());
|
||||
Evaluate();
|
||||
Thread.Sleep(delay);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user