/// <summary> /// The return type is a bit conf /// </summary> /// <param name="column"></param> private static bool ApplyGravity(SandColumn column) { var sandMoved = false; var noPressureLowerNeighbours = new Queue <SandColumn>(); Shuffle(column.Neighbours); foreach (var neighbour in column.Neighbours) { noPressureLowerNeighbours.Enqueue(neighbour); } while (noPressureLowerNeighbours.Count > 0) { var neighbour = noPressureLowerNeighbours.Dequeue(); if (neighbour.Height + 1 < column.Height && neighbour.NumExcessRoom > 0) { MoveSand(column, neighbour); sandMoved = true; if (neighbour.Height + 1 < column.Height && neighbour.NumExcessRoom > 0) { noPressureLowerNeighbours.Enqueue(neighbour); } } } return(sandMoved); }
public static SandColumn[,] CreateSandTable(int height, int width, int defaultSandHeight, int defaultHeightLimit = int.MaxValue) { var sand = new SandColumn[width, height]; for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { sand[x, y] = new SandColumn { HeightLimit = defaultHeightLimit, Height = defaultSandHeight, Location = new Point { X = x, Y = y } }; } } for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { sand[x, y].Neighbours = GetNeighbours(sand, new Point { X = x, Y = y }); Shuffle(sand[x, y].Neighbours); } } return(sand); }
private static bool SettleColumn(SandColumn column) { var columnChangedOnce = false; //if the column changed at all bool columnChanged; //if the column changed in this iteration do { columnChanged = false; var lowerPressureNeighbours = new List <SandColumn>(); var equalPressureLowerHeightNeighbours = new List <SandColumn>(); foreach (var neighbour in column.Neighbours) { if (column.Pressure > 0 && column.DecreasedPressure >= neighbour.IncreasedPressure) { lowerPressureNeighbours.Add(neighbour); } else if (column.Pressure <= 0 && neighbour.Pressure <= 0 && column.DecreasedHeight >= neighbour.IncreasedHeight) { equalPressureLowerHeightNeighbours.Add(neighbour); } } if (lowerPressureNeighbours.Count > 0) { var lowestPressure = lowerPressureNeighbours.Min(n => n.IncreasedPressure); lowerPressureNeighbours.RemoveAll(n => n.Pressure > lowestPressure); SandColumn chosenNeighbour = lowerPressureNeighbours[Rnd.Next(lowerPressureNeighbours.Count)]; MoveSand(column, chosenNeighbour); columnChanged = true; } else if (equalPressureLowerHeightNeighbours.Count > 0) { MoveSand(column, equalPressureLowerHeightNeighbours[Rnd.Next(equalPressureLowerHeightNeighbours.Count)]); columnChanged = true; } columnChangedOnce = columnChanged || columnChangedOnce; } while (columnChanged); return(columnChangedOnce); }
private static bool SettlePressuredSand(SandColumn column) { //This is a basic breadth first search using a queue if (column.Pressure <= 0) { return(false); } var sandMoved = false; var neighbourQueue = new Queue <SandColumn>(); var visitedNeighbours = new HashSet <SandColumn>(); neighbourQueue.Enqueue(column); while (column.Pressure > 0) { var currentNeighbour = neighbourQueue.Dequeue(); visitedNeighbours.Add(currentNeighbour); var emptySpace = currentNeighbour.NumExcessRoom; if (emptySpace > 0) { MoveSand(column, currentNeighbour, Math.Min(column.NumExcessSand, emptySpace)); sandMoved = true; } foreach (var currentNeighbourNeighbour in currentNeighbour.Neighbours) { if (!visitedNeighbours.Contains(currentNeighbourNeighbour)) { neighbourQueue.Enqueue(currentNeighbourNeighbour); } } } return(sandMoved); }
private static void MoveSand(SandColumn source, SandColumn dest, int amount = 1) { source.Height -= amount; dest.Height += amount; }