Там, где я работаю, мы все еще работаем на .Net 2.0, но я немного знаком с материалами 3.0 / 3.5. Я хотел немного попрактиковаться в использовании выражения linq / lambda в C #, поэтому я написал простой решатель судоку, использующий множество обобщенных List<T>
и лямбда-выражений с агрегатными методами, которые он предоставляет.
В моем решателе у меня есть это наверху алгоритма решателя:
private Puzzle RecursiveSolve(Puzzle p, int idx)
{
// start with simple filter to narrow down recursive paths
// puzzle is still solved without this line, but it takes at least 20x longer
while( p.board.Any(cell => cell.FilterPossibles()) ); // while(); <- empty while loop is intentional
Как вы, вероятно, можете сказать, это простой рекурсивный алгоритм, но я немного его оптимизировал, чтобы сократить время выполнения до чего-то разумного (3,6 с для самой сложной головоломки, которую я мог найти в Google).
Чтобы понять фрагмент, Puzzle.board
- это List<Cell>
, а Cell.FilterPossibles()
проверяет возможные значения каждой ячейки по значениям других ячеек в той же строке, столбце и блоке 3x3, чтобы увидеть, может ли он устранить их. Если он доходит до одного возможного, он устанавливает значение для ячейки и возвращает true. В противном случае возвращается false. Так что цикл while будет работать до тех пор, пока хотя бы одна ячейка на доске изменилась (была решена) в предыдущей итерации.
Что меня беспокоит, так это то, что цикл while пуст. Это похоже на запах кода и говорит мне, что я, вероятно, что-то упустил Есть ли способ, которым я мог бы написать это как утверждение, а не цикл?
В результате этого проекта у меня возникла целая куча вопросов: (Я по незнанию реализовал некоторые интерфейсы, о которых мог бы рассказать компилятору? Являются ли мои варианты выбора подходящими? У меня есть много логических методов для упрощения выражений : как это могло бы быть лучше? Как я мог бы лучше спроектировать это так, чтобы можно было использовать неизменяемые объекты Головоломка / Клетка?) Но это то, что сейчас мучает меня больше всего.