96 lines
3.1 KiB
C#
96 lines
3.1 KiB
C#
using UnityEngine;
|
|
|
|
public class Solver : MonoBehaviour
|
|
{
|
|
public static bool CheckSolved(Tile[,] tiles, int width, int height)
|
|
{
|
|
bool solved = true;
|
|
for (int x = 0; x < width; x++)
|
|
for (int y = 0; y < height; y++)
|
|
tiles[x, y].SetConnectionState(IsTileCorrectlyConnected(tiles, x, y, width, height));
|
|
|
|
foreach (var tile in tiles)
|
|
if (!IsTileCorrectlyConnected(tiles, tile.X, tile.Y, width, height))
|
|
solved = false;
|
|
|
|
return solved;
|
|
}
|
|
|
|
private static bool IsTileCorrectlyConnected(Tile[,] tiles, int x, int y, int width, int height)
|
|
{
|
|
Tile tile = tiles[x, y];
|
|
|
|
bool up = tile.HasConnection(0);
|
|
bool right = tile.HasConnection(1);
|
|
bool down = tile.HasConnection(2);
|
|
bool left = tile.HasConnection(3);
|
|
|
|
bool connected = true;
|
|
|
|
if (y < height - 1)
|
|
connected &= up == tiles[x, y + 1].HasConnection(2);
|
|
else if (up) connected = false;
|
|
|
|
if (x < width - 1)
|
|
connected &= right == tiles[x + 1, y].HasConnection(3);
|
|
else if (right) connected = false;
|
|
|
|
if (y > 0)
|
|
connected &= down == tiles[x, y - 1].HasConnection(0);
|
|
else if (down) connected = false;
|
|
|
|
if (x > 0)
|
|
connected &= left == tiles[x - 1, y].HasConnection(1);
|
|
else if (left) connected = false;
|
|
|
|
return connected;
|
|
}
|
|
|
|
public static bool AutoSolve(Tile[,] tiles, int width, int height)
|
|
{
|
|
bool changed;
|
|
int[,] possible = new int[width, height];
|
|
|
|
// Initialize the possible rotation states of all tiles (4-bit binary)
|
|
for (int x = 0; x < width; x++)
|
|
for (int y = 0; y < height; y++)
|
|
possible[x, y] = 0b1111;
|
|
|
|
int limit = width * height * 10; // Prevent infinite loops
|
|
do
|
|
{
|
|
changed = false;
|
|
|
|
for (int x = 0; x < width; x++)
|
|
for (int y = 0; y < height; y++)
|
|
{
|
|
int newMask = 0;
|
|
for (int rot = 0; rot < 4; rot++)
|
|
{
|
|
tiles[x, y].RotationState = rot;
|
|
if (IsTileCorrectlyConnected(tiles, x, y, width, height))
|
|
newMask |= (1 << rot);
|
|
}
|
|
if (newMask != possible[x, y])
|
|
{
|
|
possible[x, y] = newMask;
|
|
changed = true;
|
|
}
|
|
|
|
if (newMask == 0)
|
|
return false; // No valid direction
|
|
|
|
// If there is only one possible direction, lock it in
|
|
if ((newMask & (newMask - 1)) == 0)
|
|
{
|
|
int fixedRot = System.Convert.ToString(newMask, 2).LastIndexOf('1');
|
|
tiles[x, y].RotationState = fixedRot;
|
|
tiles[x, y].transform.rotation = Quaternion.Euler(0, 0, -90 * fixedRot);
|
|
}
|
|
}
|
|
} while (changed && --limit > 0);
|
|
|
|
return CheckSolved(tiles, width, height);
|
|
}
|
|
}
|