0

例如,假设我们有一个这样的数独板:

0 0 6 5 8 9 7 4 3
0 5 0 0 0 0 0 6 0
7 0 9 0 6 0 1 0 0
0 3 0 0 0 2 0 8 7
0 0 1 0 0 0 4 0 0
8 9 0 6 0 0 0 5 0
0 0 2 0 5 0 3 0 6
0 7 0 0 0 0 0 9 0
3 1 8 4 9 6 5 0 0

我想将它存储到一个数组中,这样数组的前 9 个元素是第一个子块,即值{0 0 6 0 5 0 7 0 9},然后是{5 8 9 0 0 0 0 6 0}.

我试过找到一个解决方案,但我总是得到一个数组索引超出范围的错误,而且它太暴力了。与此类似的东西:

          while(st.hasMoreTokens()) {
            if(ctr == 27) {
                c.addSubBlock(sb1);
                c.addSubBlock(sb2);
                c.addSubBlock(sb3);
                sb1 = new SubBlock();
                sb2 = new SubBlock();
                sb3 = new SubBlock();
                ctr = 0;
            }
            sb1.addElement(Integer.parseInt(st.nextToken()));
            sb1.addElement(Integer.parseInt(st.nextToken()));
            sb1.addElement(Integer.parseInt(st.nextToken()));
            sb2.addElement(Integer.parseInt(st.nextToken()));
            sb2.addElement(Integer.parseInt(st.nextToken()));
            sb2.addElement(Integer.parseInt(st.nextToken()));
            sb3.addElement(Integer.parseInt(st.nextToken()));
            sb3.addElement(Integer.parseInt(st.nextToken()));
            sb3.addElement(Integer.parseInt(st.nextToken()));
            ctr+=9;
        }

请给我一些提示。代码片段也会有很大帮助。

编辑:这个线程以某种方式帮助我弄清楚了。是的,这是数独的一部分,我试图将板编码成一个数组。

我所做的是首先将输入字符串转换为二维数组(9x9)并用于int block = (row/3)*3 + (col/3);准确计算每个元素所属的子块。

4

5 回答 5

2
  1. 创建一个 3x3 的子块数组
  2. 使用 2 个计数器 (x & y) 跟踪读取的每个元素在全板上的位置
  3. 将 (x,y) 处的值添加到子块 (x/3,y/3)

像这样的东西:

SubBlock board[][] = new SubBlock[3][3];
int x, y;
for ( y=0; y<9; y++ )
  for ( x=0; x<9; x++ )
    board[y/3][x/3].addElement(Integer.parseInt(st.nextToken()));

board[0][0] 将是左上角的子块, board[2][2] 是右下角的子块。

于 2012-02-22T17:20:37.443 回答
1

将所有内容存储在二维数组中。例如

int[] board = {
{1,2,3,4,5,6,7,8,9}
{1,2,3,4,5,6,7,8,9}
{1,2,3,4,5,6,7,8,9}
{1,2,3,4,5,6,7,8,9}
{1,2,3,4,5,6,7,8,9}
{1,2,3,4,5,6,7,8,9}
{1,2,3,4,5,6,7,8,9}
{1,2,3,4,5,6,7,8,9}
{1,2,3,4,5,6,7,8,9}};

//looping
public static void Main(string[] args){
  for(int i = 0; i < 9; i++)
  {
    System.out.println("SubBlock number"+i);
    for(int j = 0; j < 9; j++){
      System.out.println(board[i][j]);
    }
  }
}
于 2012-02-22T17:24:50.293 回答
0

我不完全确定您是否想要一个单维数组的答案,或者您是否愿意将其设为二维数组(正如您提到的用花括号设置的每个九个元素),但如果二维是好的...

此代码审查帖子中的OP使用了一种“奇特”的方式来筛选子网格,方法是(i % 3) + rowStart在一个方括号内和(i / 3) + colStart另一个方括号内使用数学。一位评论者指出这种模数方法有点晦涩,我倾向于同意,但对于它的清洁程度和它的工作原理,我认为这是一个可靠的解决方案。因此,结合 for 循环的迭代,我们可以筛选每个“子网格”单元格,以及 row + col 的每个元素。

for(i=0; i<9; ++i)
{
    if (puzzle[row][i] == num) return 0;
    if (puzzle[i][col] == num) return 0;
    if (puzzle[rowStart + (i%3)][colStart + (i/3)] == num) return 0;
}

如果我们在其中一个匹配的单元格中找到一个数字,则它是重复的,我们将函数作为“假”或 0 退出。

编辑:

现在我想到了,您可以通过使用而不是 3 来对单维数组使用相同的技巧。i % 9然后您可以通过这样做并相信它来确定我们在哪个“行”上i / 9,因为我们正在处理类型ints,我们将截断不必要的小数。

这确实验证了这个技巧有点倾向于 N-1 索引数据,因为有人会假设“转到第 81 个元素”意味着转到第 9 行的第 9 列,但使用 81 % 9 会产生 0,并且81 / 9 将产生 9,因此我们将转到第 9 行的第 0 位。

于 2014-04-23T10:41:36.680 回答
0

如果我们知道您为什么要尝试遍历电路板,那就太好了。

如果您想检查是否可以输入数字,我建议您为每个 3x3 方格使用地图。
然后检查该项目是否已经在地图中。对于行和列,您可以遍历 2D 数组并检查每个元素,或者 - 再次 - 对每一列使用一个映射,对每一行使用一个映射。

于 2012-02-22T17:42:57.543 回答
0

假设您正在从左到右、从上到下读取输入,请尝试一组 4 个嵌套循环,如下所示:

int board[] = new int[81];
for (int outY = 0; outY < 3; outY++)
{
   for (int outX = 0; outX < 3; outX++)
   {
      for (int inY = 0; inY < 3; inY++)
      {

         for (int inX = 0; inX < 3; inX++)
         {
             board[27*outY + 9*outX + 3 * inY + inX] = //parse an int from your input here
         }
      }        
   }    
}
于 2012-02-22T17:27:49.420 回答