Last active
September 3, 2024 01:28
-
-
Save itarato/0d6e65d538e42f559ada80decc0acc5f to your computer and use it in GitHub Desktop.
Slider puzzle generator (crap)
This file contains hidden or 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 static Program.Generator; | |
class Program { | |
public class Generator { | |
public enum Orientation { | |
Vertical, | |
Horizontal, | |
} | |
public class Slider { | |
public int id; | |
public Orientation orientation; | |
public int len; | |
public int x; | |
public int y; | |
public int cachedMinBound = 0; | |
public int cachedMaxBound = 5; | |
public Slider(int id, Orientation orientation, int len, int x, int y) { | |
this.id = id; | |
this.orientation = orientation; | |
this.len = len; | |
this.x = x; | |
this.y = y; | |
} | |
public bool IsVertical() { | |
return orientation == Orientation.Vertical; | |
} | |
public (int, int)[] GetCoords() { | |
(int, int)[] coords = new (int, int)[len]; | |
if (IsVertical()) { | |
for (int i = 0; i < len; i++) coords[i] = (5 - y - i, x); | |
} else { | |
for (int i = 0; i < len; i++) coords[i] = (5 - y, x + i); | |
} | |
return coords; | |
} | |
} | |
public void Generate(int sliderCount, int moveCount) { | |
if (sliderCount <= 0) throw new ArgumentException("Slider count must be greater than 1"); | |
List<Slider> sliders = new List<Slider>(); | |
// The exit slider (mandatory). | |
sliders.Add(new Slider(0, Orientation.Horizontal, 2, 4, 3)); | |
int[,] memory = BuildMemoryForSliders(sliders); | |
Random rnd = new Random(); | |
for (int id = 1; id <= sliderCount; id++) { | |
int len = rnd.Next(2, 4); | |
Orientation orientation = (rnd.Next(2) == 0) ? Orientation.Horizontal : Orientation.Vertical; | |
// Find all possible places for a `len` and `orientation`. | |
List<(int, int)> availableSlots = AvailableSlotsForLen(len, orientation, memory); | |
if (availableSlots.Count == 0) { | |
Console.WriteLine("Out of options. Cannot complete generation."); | |
return; | |
} | |
(int, int) pickedCoord = availableSlots[rnd.Next(availableSlots.Count)]; | |
Slider newSlider = new Slider(id, orientation, len, pickedCoord.Item1, pickedCoord.Item2); | |
sliders.Add(newSlider); | |
RecordSliderFootprintOnMemory(newSlider, memory); | |
} | |
// Pre shuffle state. | |
DebugMemory(memory); | |
for (int _attempt = 0; _attempt < moveCount; _attempt++) { | |
int slideIdx = rnd.Next(sliders.Count); | |
List<(int, int)> availableMoves = AvailableMoveForSlider(sliders[slideIdx], memory); | |
if (availableMoves.Count == 0) continue; | |
Console.WriteLine("Moving {0} AvailableMoves {1}", slideIdx, availableMoves.Count); | |
// Update slider. | |
(int, int) selectedMove = availableMoves[rnd.Next(availableMoves.Count)]; | |
sliders[slideIdx].x = selectedMove.Item1; | |
sliders[slideIdx].y = selectedMove.Item2; | |
// Refresh memory. | |
memory = BuildMemoryForSliders(sliders); | |
DebugMemory(memory); | |
} | |
} | |
private int[,] BuildMemoryForSliders(List<Slider> sliders) { | |
int[,] memory = new int[6, 6]; | |
for (int i = 0; i < 6; i++) for (int j = 0; j < 6; j++) memory[i, j] = -1; | |
foreach (Slider slider in sliders) RecordSliderFootprintOnMemory(slider, memory); | |
return memory; | |
} | |
private void RecordSliderFootprintOnMemory(Slider slider, int[,] memory) { | |
foreach ((int, int)coord in slider.GetCoords()) { | |
if (memory[coord.Item1, coord.Item2] != -1) throw new ApplicationException("Occupied memory slot"); | |
memory[coord.Item1, coord.Item2] = slider.id; | |
} | |
} | |
private List<(int, int)> AvailableSlotsForLen(int len, Orientation orientation, int[,] memory) { | |
List<(int, int)> coords = new List<(int, int)>(); | |
if (orientation == Orientation.Vertical) { | |
for (int y = 6 - len; y >= 0; y--) { | |
for (int x = 0; x < 6; x++) { | |
bool failed = false; | |
for (int i = 0; i < len; i++) { | |
if (memory[5 - y - i, x] != -1) { | |
failed = true; | |
break; | |
} | |
} | |
if (!failed) coords.Add((x, y)); | |
} | |
} | |
} else { | |
for (int y = 0; y < 6; y++) { | |
for (int x = 0; x <= 6 - len; x++) { | |
bool failed = false; | |
for (int i = 0; i < len; i++) { | |
if (memory[5 - y, x + i] != -1) { | |
failed = true; | |
break; | |
} | |
} | |
if (!failed) coords.Add((x, y)); | |
} | |
} | |
} | |
return coords; | |
} | |
private List<(int, int)> AvailableMoveForSlider(Slider slider, int[,] memory) { | |
List<(int, int)> coords = new List<(int, int)> (); | |
if (slider.IsVertical()) { | |
// Min-side. | |
for (int i = slider.y - 1; i >= 0; i--) { | |
if (memory[5 - i, slider.x] == -1) { | |
coords.Add((slider.x, i)); | |
} else break; | |
} | |
// Max-side. | |
for (int i = slider.y + 1; i + slider.len <= 6; i++) { | |
if (memory[5 - i - slider.len + 1, slider.x] == -1) { | |
coords.Add((slider.x, i)); | |
} else break; | |
} | |
} else { | |
// Min-side. | |
for (int i = slider.x - 1; i >= 0; i--) { | |
if (memory[5 - slider.y, i] == -1) { | |
coords.Add((i, slider.y)); | |
} else break; | |
} | |
// Max-side. | |
for (int i = slider.x + 1; i + slider.len <= 6; i++) { | |
if (memory[5 - slider.y, i + slider.len - 1] == -1) { | |
coords.Add((i, slider.y)); | |
} else break; | |
} | |
} | |
return coords; | |
} | |
private static void DebugMemory(int[,] memory) { | |
Console.WriteLine(" 012345"); | |
for (int i = 0; i < 6; i++) { | |
Console.Write("{0} ", 5 - i); | |
for (int j = 0; j < 6; j++) { | |
if (memory[i, j] == -1) { | |
Console.Write("\x1B[90m█\x1B[0m"); | |
} else { | |
Console.Write("\x1B[{0}m█\x1B[0m", 97 - memory[i, j]); | |
} | |
} | |
Console.WriteLine(); | |
} | |
} | |
} | |
public static void Main(string[] args) { | |
Generator generator = new Generator(); | |
generator.Generate(6, 1000); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment