如何在数独板上循环?

时间:2012-02-22 17:16:42

标签: java sudoku

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

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;
        }

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

编辑:这thread以某种方式帮助我弄明白了。是的,这是Sudoku的一部分,我正在尝试将电路板编码为阵列。

我所做的是首先将输入String转换为2d数组(9x9)并使用int block = (row/3)*3 + (col/3);来精确计算每个元素所属的子块。

5 个答案:

答案 0 :(得分:2)

  1. 创建一个3x3子块数组
  2. 使用2个计数器(x& y)跟踪每个元素读取的整个电路板中的位置
  3. 将(x,y)的值添加到子块(x / 3,y / 3)
  4. 这样的事情:

    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]将是左上角的SubBlock,board [2] [2]是右下角的。

答案 1 :(得分:1)

将所有内容存储在二维数组中。 E.g。

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]);
    }
  }
}

答案 2 :(得分: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
         }
      }        
   }    
}

答案 3 :(得分:0)

如果我们知道你为什么试图在董事会中盘旋,那就太好了。

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

答案 4 :(得分:0)

我不完全确定你是否想要一个单维数组的答案,或者你是否愿意让它成为一个二维数组(正如你提到每个九个带花括号的元素集),但如果两个-dimensional可以......

OP in this Code Review posting使用“花式”筛选子网格的方法,使用方括号内的数学(i % 3) + rowStart和另一方内的(i / 3) + colStart。一位评论者注意到这种模数方法有点模糊,我很容易同意,但是对于它的清洁程度以及它的工作原理,我认为这是一个可靠的解决方案。因此,与for循环的迭代配对,我们可以筛选每个'subgrid'单元格,以及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;
}

如果我们在其中一个匹配的单元格中找到一个数字,则它是重复的,我们将该函数退出为'false',或者为0.

修改

现在我想起来了,你可以使用i % 9而不是3来对单维数组使用相同的技巧。然后你可以通过{{1}确定我们在哪个“行”并且相信,因为我们正在处理类型i / 9,所以我们将截断不必要的小数。

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