using UnityEngine; using System.Linq; using System.Collections.Generic; public class Solver : MonoBehaviour { public static bool CheckSolved(Tile[,] tiles, int width, int height) { // First check if all tiles are in their correct rotation bool allCorrect = true; foreach (var tile in tiles) { bool correct = tile.IsCorrectlyOriented(); tile.SetConnectionState(correct); if (!correct) allCorrect = false; } if (!allCorrect) return false; // Then verify the entire network is connected return IsNetworkFullyConnected(tiles, width, height); } private static bool IsNetworkFullyConnected(Tile[,] tiles, int width, int height) { // Find the center tile (or first active tile if center isn't marked) int startX = width / 2; int startY = height / 2; // If center isn't marked, find first active tile if (!tiles[startX, startY].isCenterTile) { for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { if (tiles[x, y].GetConnectionCount() > 0) { startX = x; startY = y; break; } } } } bool[,] visited = new bool[width, height]; FloodFill(tiles, visited, width, height, startX, startY); // Check if all tiles with connections were visited for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { if (tiles[x, y].GetConnectionCount() > 0 && !visited[x, y]) return false; } } return true; } private static void FloodFill(Tile[,] tiles, bool[,] visited, int width, int height, int x, int y) { if (x < 0 || x >= width || y < 0 || y >= height || visited[x, y]) return; visited[x, y] = true; Tile tile = tiles[x, y]; // Check all 4 directions for (int dir = 0; dir < 4; dir++) { if (tile.HasConnection(dir)) { int nx = x + directions[dir].x; int ny = y + directions[dir].y; // Wrap coordinates if needed (you'll need to pass wrapping info to solver) if (nx < 0) nx = width - 1; else if (nx >= width) nx = 0; if (ny < 0) ny = height - 1; else if (ny >= height) ny = 0; // Only continue if neighbor has matching connection if (tiles[nx, ny].HasConnection((dir + 2) % 4)) { FloodFill(tiles, visited, width, height, nx, ny); } } } } public static bool AutoSolve(Tile[,] tiles, int width, int height) { // Create a list of tiles sorted by connection count (most constrained first) var tileList = tiles.Cast() .Where(t => !t.locked) .OrderBy(t => t.GetConnectionCount()) .ToList(); return SolveRecursive(tiles, width, height, tileList, 0); } private static bool SolveRecursive(Tile[,] tiles, int width, int height, List tileList, int index) { if (index >= tileList.Count) return CheckSolved(tiles, width, height); Tile tile = tileList[index]; // Try all possible rotations for this tile for (int rot = 0; rot < 4; rot++) { tile.RotationState = rot; tile.transform.rotation = Quaternion.Euler(0, 0, -90 * rot); // Early pruning - check if this rotation causes immediate conflicts if (!HasImmediateConflicts(tiles, width, height, tile)) { if (SolveRecursive(tiles, width, height, tileList, index + 1)) return true; } } return false; } private static bool HasImmediateConflicts(Tile[,] tiles, int width, int height, Tile tile) { int x = tile.X; int y = tile.Y; // Check all 4 directions for conflicts for (int dir = 0; dir < 4; dir++) { if (tile.HasConnection(dir)) { int nx = x + directions[dir].x; int ny = y + directions[dir].y; // Wrap coordinates if needed if (nx < 0) nx = width - 1; else if (nx >= width) nx = 0; if (ny < 0) ny = height - 1; else if (ny >= height) ny = 0; Tile neighbor = tiles[nx, ny]; int oppositeDir = (dir + 2) % 4; // If neighbor is locked and doesn't have matching connection, conflict if (neighbor.locked && !neighbor.HasConnection(oppositeDir)) return true; } } return false; } // Directions: Right, Up, Left, Down (matches Net game encoding) private static readonly Vector2Int[] directions = { new Vector2Int(1, 0), // R new Vector2Int(0, 1), // U new Vector2Int(-1, 0), // L new Vector2Int(0, -1) // D }; }