Ваш HashSet
подход выглядит довольно хорошо, но нужно немного тонкой настройки ...
предположение: когда первый блок является дублированием, и одно и то же положение во всех блоках также не содержит дублирования, затем разрешается судоку.
В вашем внешнем цикле вы должны пройти только значения первого блока.
Вы должны добавить текущее значение на «обратный набор первого блока» и проверьте, что все блоки имеют различное количество в том же положении, с помощью внутреннего контура со своим собственным «проверки набора»:
First iteration
1## 2## 3##
### ### ###
### ### ###
4## 5## 5##
### ### ###
### ### ###
7## 8## 9##
### ### ###
### ### ###
firstBlock: [1]
second iteration
#2# #3# #4#
### ### ###
### ### ###
#5# #6# #7#
### ### ###
### ### ###
#8# #9# #1#
### ### ###
### ### ###
firstBlock: [1,2]
Большой трюк заключается в том, чтобы избежать отдельных петель для координат x
и y
.
Поскольку Java является объектно-ориентированный язык программирования я предлагаю использовать объекты для определения координат. Мы могли бы держать их в массиве (установить закладку, я обычно говорю «Коллекция» вместо этого ...) и повторить ее с помощью простого контура печки ...
Также мы должны иметь дело с количеством исправленных объектов мы знаем заранее (там 9 блоков с 9 позиций в каждой ...) поэтому я предлагаю использовать Java enums
так: так что вы логика должна выглядеть следующим образом:
public class SudokuCheck {
enum SudokuPosition {
p11(0, 0), p12(0, 1), p13(0, 2),
p21(1, 0), p22(1, 1), p23(1, 2),
p31(2, 0), p32(2, 1), p33(2, 2);
private final int x;
private final int y;
SudokuPosition(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {return x;}
public int getY() {return y;}
}
boolean check(int[][] sudoku) {
Set<Integer> firstBlockUniqueNumbers = new HashSet<>();
for (SudokuPosition inBlock : SudokuPosition.values()) {
firstBlockUniqueNumbers.add(sudoku[inBlock.x][inBlock.y]);
Set<Integer> samePosInOtherBlocksUniqueNumbers = new HashSet<>();
for (SudokuPosition ofBlock : SudokuPosition.values()) {
int sameXinAll = inBlock.x + offset(ofBlock.x);
int sameYinAll = inBlock.y + offset(ofBlock.y);
samePosInOtherBlocksUniqueNumbers.add(sudoku[sameXinAll][sameYinAll]);
}
if (9 > samePosInOtherBlocksUniqueNumbers.size())
// numbers where not unique at current block position
// through all the blocks
return false;
}
return 9 == firstBlockUniqueNumbers.size();
}
private int offset(int xOrY) {
return xOrY * 3;
}
}
Я надеюсь, продемонстрировал полезность Переменные Java и насколько важны имена хороших идентификаторов.
Я думаю, что этот подход может быть улучшена 2-мя способами:
- с использованием Java 8 Стрим API может заменить forech петли
- имена элементов позиции как-то повторить их значения конструктора, которые могут привести к неприятные ошибки.Последнее может быть заменено каким-то умным расчетом на постоянное имя, которое доступно через
name()
, но для этой демонстрации оно может быть достаточно хорошим, так как оно ...
Получил! Прежде чем я приму ответ и вернемся, еще несколько вопросов. Как получается, что 'int ox = offset% 3;' и 'int oy = offset/3;' помогают прокручивать сетку 3x3? И почему «HashSet» над другими? –
также, тогда в случае сказать '0,6' будет округлено до 1? или все еще быть '0'? –
@KuNole Добавьте 'System.out.println', чтобы увидеть, какие' x + ox' и 'y + oy' находятся в точке, где он получает значение от' board'. Тогда вы сможете увидеть. – ajb