private static void PrintTile(StatefulTile tileDiagA) { PrintFace(tileDiagA, 0); Console.Write("| "); PrintFace(tileDiagA, 1); Console.WriteLine(); }
private static RowNode CopyAndRemove(RowNode row, StatefulTile tile) { var result = CopyRow(row); result.Row.Remove(tile); return(result); }
private static void SwapRow(ref StatefulTile[,] board, int a, int b) { var temp = new StatefulTile[4]; for (var k = 0; k < 4; k++) { temp[k] = board[b, k]; board[b, k] = board[a, k]; board[a, k] = temp[k]; } }
private static void SwapCol(ref StatefulTile[,] board, int a, int b) { var temp = new StatefulTile[4]; for (var k = 0; k < 4; k++) { temp[k] = board[k, b]; board[k, b] = board[k, a]; board[k, a] = temp[k]; } }
private static (int, int) GetTileLocation(StatefulTile[,] board, StatefulTile tile) { for (var i = 0; i < 4; i++) { for (var j = 0; j < 4; j++) { if (board[i, j] == tile) { return(i, j); } } } return(-1, -1); }
private static IList <StatefulTile> GetAllStatefulTiles(IList <Tile> allTiles) { var allStatefulTiles = new List <StatefulTile>(); foreach (var tile in allTiles) { var a = new StatefulTile(tile, new List <int> { 0, 1 }); var b = new StatefulTile(tile, new List <int> { 1, 0 }); a.StatefulTileTwin = b; b.StatefulTileTwin = a; allStatefulTiles.Add(a); allStatefulTiles.Add(b); } return(allStatefulTiles); }
private static void PrintFace(StatefulTile tile, int i) => Console.Write(tile.GetFaceValue(i).ToString().PadRight(3));
private static bool IsSameTile(StatefulTile a, StatefulTile b) => a == b || a == b.StatefulTileTwin;
private static void GroupsOfFour(IList <Tile> allTiles) { // get all stateful tiles Console.WriteLine("Getting all stateful tiles..."); var allStatefullTiles = GetAllStatefulTiles(allTiles); Console.WriteLine($"Got {allStatefullTiles.Count()} stateful tiles."); // get all rows Console.WriteLine("Getting rows..."); var validRows = new List <RowNode>(); // for each possible row combination foreach (var statefulTileCombination in new Combinations <StatefulTile>(allStatefullTiles, 4)) { if (ValidRow(statefulTileCombination)) { // row is valid // create row node var rowNode = new RowNode(statefulTileCombination); // add row node to list of valid rows validRows.Add(rowNode); foreach (var tile in rowNode.Row) { // link tile back to row that it is in tile.RowNodes.Add(rowNode); } } } Console.WriteLine($"Got {validRows.Count} rows."); // find valid grids Console.WriteLine("Finding valid grids...\n"); // for each valid row... foreach (var rowA in validRows) { // choose a tile for col A var tileA = rowA.Row[0]; // find all possible rows that could be the col for this tile // of the rows that include tile A... var validColAs = tileA.RowNodes.Where(x => // where row is not row A and its not the case that... x != rowA && !x.Row.Any(y => // there is a tile other than tile A that is in both row A and the col A y != tileA && rowA.Row.Any(z => IsSameTile(y, z)))); foreach (var colA in validColAs) { // do the same for another tile from row A var tileB = rowA.Row[1]; var validColBs = tileB.RowNodes.Where(x => // row must now also not be col A x != rowA && x != colA && !x.Row.Any(y => y != tileB // also check col A for matching tiles && (rowA.Row.Any(z => IsSameTile(y, z)) || colA.Row.Any(z => IsSameTile(y, z))))); foreach (var colB in validColBs) { // third tile var tileC = rowA.Row[2]; var validColCs = tileC.RowNodes.Where(x => x != rowA && x != colA && x != colB && !x.Row.Any(y => y != tileC && (rowA.Row.Any(z => IsSameTile(y, z)) || colA.Row.Any(z => IsSameTile(y, z)) || colB.Row.Any(z => IsSameTile(y, z))))); foreach (var colC in validColCs) { // fourth and last tile var tileD = rowA.Row[3]; var validColDs = tileD.RowNodes.Where(x => x != rowA && x != colA && x != colB && x != colC && !x.Row.Any(y => y != tileD && (rowA.Row.Any(z => IsSameTile(y, z)) || colA.Row.Any(z => IsSameTile(y, z)) || colB.Row.Any(z => IsSameTile(y, z)) || colC.Row.Any(z => IsSameTile(y, z))))); foreach (var colD in validColDs) { // create new objects and remove row A from the cols var colARowB = CopyAndRemove(colA, tileA); var colBRowB = CopyAndRemove(colB, tileB); var colCRowB = CopyAndRemove(colC, tileC); var colDRowB = CopyAndRemove(colD, tileD); var validRowBs = validRows.Except( new List <RowNode> { rowA, colA, colB, colC, colD }) .Where(x => colARowB.Row.Any(y => x.Row.Contains(y)) && colBRowB.Row.Any(y => x.Row.Contains(y)) && colCRowB.Row.Any(y => x.Row.Contains(y)) && colDRowB.Row.Any(y => x.Row.Contains(y))); foreach (var rowB in validRowBs) { var colARowC = CopyRow(colARowB); var colBRowC = CopyRow(colBRowB); var colCRowC = CopyRow(colCRowB); var colDRowC = CopyRow(colDRowB); foreach (var tile in rowB.Row) { colARowC.Row.Remove(tile); colBRowC.Row.Remove(tile); colCRowC.Row.Remove(tile); colDRowC.Row.Remove(tile); } var validRowCs = validRows.Except( new List <RowNode> { rowA, rowB, colA, colB, colC, colD }) .Where(x => colARowC.Row.Any(y => x.Row.Contains(y)) && colBRowC.Row.Any(y => x.Row.Contains(y)) && colCRowC.Row.Any(y => x.Row.Contains(y)) && colDRowC.Row.Any(y => x.Row.Contains(y))); foreach (var rowC in validRowCs) { var colARowD = CopyRow(colARowC); var colBRowD = CopyRow(colBRowC); var colCRowD = CopyRow(colCRowC); var colDRowD = CopyRow(colDRowC); foreach (var tile in rowC.Row) { colARowD.Row.Remove(tile); colBRowD.Row.Remove(tile); colCRowD.Row.Remove(tile); colDRowD.Row.Remove(tile); } var rowD = validRows.Except( new List <RowNode> { rowA, rowB, rowC, colA, colB, colC, colD }) .SingleOrDefault(x => colARowD.Row.Any(y => x.Row.Contains(y)) && colBRowD.Row.Any(y => x.Row.Contains(y)) && colCRowD.Row.Any(y => x.Row.Contains(y)) && colDRowD.Row.Any(y => x.Row.Contains(y))); if (rowD != null) { // create and organise board as 2D array var board = new StatefulTile[4, 4]; var i = 0; // apply row A foreach (var tile in rowA.Row) { board[0, i++] = tile; } // apply row B board[1, 0] = colA.Row.Single(x => rowB.Row.Contains(x)); board[1, 1] = colB.Row.Single(x => rowB.Row.Contains(x)); board[1, 2] = colC.Row.Single(x => rowB.Row.Contains(x)); board[1, 3] = colD.Row.Single(x => rowB.Row.Contains(x)); // apply row C board[2, 0] = colA.Row.Single(x => rowC.Row.Contains(x)); board[2, 1] = colB.Row.Single(x => rowC.Row.Contains(x)); board[2, 2] = colC.Row.Single(x => rowC.Row.Contains(x)); board[2, 3] = colD.Row.Single(x => rowC.Row.Contains(x)); // apply row D board[3, 0] = colA.Row.Single(x => rowD.Row.Contains(x)); board[3, 1] = colB.Row.Single(x => rowD.Row.Contains(x)); board[3, 2] = colC.Row.Single(x => rowD.Row.Contains(x)); board[3, 3] = colD.Row.Single(x => rowD.Row.Contains(x)); //PrintBoard(board); var possibleDiagAs = validRows.Except(new List <RowNode> { rowA, rowB, rowC, rowD, colA, colB, colC, colD }); foreach (var possibleDiagA in possibleDiagAs) { CheckDiag( validRows, rowA, rowB, rowC, rowD, colA, colB, colC, colD, possibleDiagA, (StatefulTile[, ])board.Clone()); } } } } } } } } } Console.WriteLine($"Found {validSolutions} valid grids."); }