这是一个很好的问题,我很无聊,所以这里有一个相当完整的描述一种方法。当然,还有很多!这种方法很有效,但不是特别优雅。我想看看其他人的想法。
1)BitSet
为每行、每列和 3x3 正方形制作一个对象。将它们放入数组中,如下所示:
// Initialize arrays
BitSet[] rows = new BitSet[9];
BitSet[] cols = new BitSet[9];
BitSet[] squares = new BitSet[9];
// Initialize the array elements
for(int i=0;i<9;i++){
rows[i] = new BitSet(9);
cols[i] = new BitSet(9);
squares[i] = new BitSet(9);
}
现在我们可以一次遍历网格并在适当的行、列和正方形中设置一个位。“适当”的意思是,如果我们正在查看第 i行和第j列,我们将在 and 中设置rows[i]
位cols[j]
。为了索引正方形的元素,我们将使用以下布局:
0 1 2
3 4 5
6 7 8
我们可以通过简单地将 i 和 j 除以 3 得到上述布局中的行和列。所以我们想要的索引是i / 3 + 3 * ( j / 3 )
。请注意,整数除法在这里起作用,因此7 / 3 == 8 / 3 == 2
,这意味着 i 和 j 等于 8,我们有例如8 / 3 + 3 * ( 8 / 3 ) = 2 + 3 * 2 = 8
。
综上所述,我们可以编写方法来检查谜题是否未解决,如下所示:
public boolean hasRepeats(){
// ...
// initialize rows, cols, and squares as above
// ...
for(int i=0;i<9;i++){
for(int j=0;j<9;j++){
int gridValue = grid[i + 9 * j];
if( gridValue == -1 ){
// Skip empty squares
continue;
}
// Check for repeats
if( rows[i].get(gridValue) ){
return true;
}
rows[i].set(gridValue);
if( cols[j].get(gridValue) ){
return true;
}
cols[j].set(gridValue);
BitSet square = squares[ i / 3 + 3 * ( j / 3 ) ]
if( square.get( gridValue ) ){
return true;
}
square.set( gridValue );
}
}
return false;
}