/// <summary> /// Generate a puzzle with the specified information. /// </summary> /// <param name="max">The maximum hints of the puzzle.</param> /// <param name="symmetricalType"> /// The symmetry type flags. The <see cref="SymmetryType"/> is /// a flag type, you can use bit operators to accumulate multiple /// symmetrical types such as <c><see cref="AntiDiagonal"/> | <see cref="Diagonal"/></c>, /// which means that the solver will generate anti-diagonal type or /// diagonal type puzzles. /// </param> /// <returns>The grid.</returns> /// <seealso cref="SymmetryType"/> public IReadOnlyGrid Generate(int max, SymmetryType symmetricalType) { var puzzle = new StringBuilder(Grid.EmptyString); var solution = new StringBuilder(Grid.EmptyString); GenerateAnswerGrid(puzzle, solution); // Now we remove some digits from the grid. var allTypes = from st in EnumEx.GetValues <SymmetryType>() where st != None && symmetricalType.HasFlag(st) select st; int count = allTypes.Count(); if (count == 0) { allTypes = new[] { None }; } var tempSb = new StringBuilder(solution.ToString()); string result; do { var selectedType = allTypes.ElementAt(Rng.Next(count)); for (int i = 0; i < 81; i++) { solution[i] = tempSb[i]; } var totalMap = GridMap.Empty; do { int cell; do { cell = Rng.Next(0, 81); } while (totalMap[cell]); int r = cell / 9, c = cell % 9; // Get new value of 'last'. var tempMap = GridMap.Empty; foreach (int tCell in selectedType switch { Central => new[] { r * 9 + c, (8 - r) * 9 + 8 - c }, Diagonal => new[] { r * 9 + c, c * 9 + r }, AntiDiagonal => new[] { r * 9 + c, (8 - c) * 9 + 8 - r }, XAxis => new[] { r * 9 + c, (8 - r) * 9 + c }, YAxis => new[] { r * 9 + c, r * 9 + 8 - c }, DiagonalBoth => new[] { r * 9 + c, c * 9 + r, (8 - c) * 9 + 8 - r, (8 - r) * 9 + 8 - c }, AxisBoth => new[] { r * 9 + c, (8 - r) * 9 + c, r * 9 + 8 - c, (8 - r) * 9 + 8 - c }, All => new[] { r * 9 + c, r * 9 + (8 - c), (8 - r) * 9 + c, (8 - r) * 9 + (8 - c), c * 9 + r, c * 9 + (8 - r), (8 - c) * 9 + r, (8 - c) * 9 + (8 - r) }, None => new[] { r * 9 + c }, _ => throw Throwings.ImpossibleCaseWithMessage("You should not add an option that does not contain in the table of symmetrical types.") }) { solution[tCell] = '0'; totalMap.Add(tCell); tempMap.Add(tCell); } } while (81 - totalMap.Count > max); } while (!FastSolver.CheckValidity(result = solution.ToString(), out _));