I am writing a Sudoku application and am currently working on the game generation algorithm. I managed to figure out how to quickly generate a solution (not solve). I am stumped on how to remove some of the numbers to actually make it into a puzzle, though. My first inclination was to randomly remove a certain number of cells based on the difficulty, but that is not the correct algorithm, because it often renders a puzzle that is unsolvable or has multiple solutions. It also might generate puzzles that don't reflect the requested difficulty.
Here is the code that I have so far. I removed most of the irrelevant code, but if you would like to see something that isn't implemented but used below, please let me know. I can also provide my attempt at the Puzzlefy
method if you would like, but I opted out of immediately posting it since it's blatantly wrong (even though it "works").
using System;
using System.Collections.Generic;
using System.Linq;
namespace Sudoku
{
public class Game
{
public enum Difficulty
{
VeryEasy,
Easy,
Medium,
Difficult,
Evil
}
private readonly int?[,] _currentItems = new int?[9,9];
private readonly int?[,] _solution = new int?[9,9];
private readonly int?[,] _startingItems = new int?[9,9];
private readonly Difficulty _difficulty;
public Game(Difficulty difficulty)
{
_difficulty = difficulty;
GenerateSolution();
Puzzlefy();
}
private void GenerateSolution()
{
var random = new Random();
var availableNumbers = new Stack<List<int?>>(81);
var x = 0;
var y = 0;
availableNumbers.Push(AllowableNumbers(_solution, 0, 0).ToList());
while (x < 9 && y < 9)
{
var currentAvailableNumbers = AllowableNumbers(_solution, x, y).ToList();
availableNumbers.Push(currentAvailableNumbers);
// back trace if the board is in an invalid state
while (currentAvailableNumbers.Count == 0)
{
_solution[x, y] = null;
availableNumbers.Pop();
currentAvailableNumbers = availableNumbers.Peek();
x -= y >= 1 ? 0 : 1;
y = y >= 1 ? y - 1 : 8;
}
var index = random.Next(currentAvailableNumbers.Count);
_solution[x, y] = currentAvailableNumbers[index];
currentAvailableNumbers.RemoveAt(index);
x += y < 8 ? 0 : 1;
y = y < 8 ? y + 1 : 0;
}
}
private void Puzzlefy()
{
CopyCells(_solution, _startingItems);
// remove some stuff from _startingItems
CopyCells(_startingItems, _currentItems);
}
}
}
I am not looking for code, rather an algorithm. How would I go about removing the numbers from the solution to make it into a puzzle?