Java中的数独。超出界限的索引

时间:2013-07-03 17:36:35

标签: arrays arraylist

我在以下程序中遇到了IndexOutOfBounds异常。它由三个文件组成:

重要的只有两个,GUI工作正常。这是第一个:

interface SudokuObserver {
    public void modified(int i, int j);
}

public class SudokuData
{
    public int[][] feld = new int[9][9];
    public SudokuObserver obs = null;

    public SudokuData()
    {
        int i,j;
        for (i=0; i<9; i++) {
            for (j=0; j<9; j++) {
                feld[i][j] = 0;
            }
        }
    }

    public int getNumber(int x, int y)
    {
        return feld[x][y];
    }

    public void setNumber(int x, int y, int v)
    {
        feld[x][y] = v;
        if (obs != null)
            obs.modified(x, y);
    }

    public void setObserver(SudokuObserver o)
    {
        obs = o;
    }

所以Sudoku字段被分配为9x9整数数组。以下文件名为SudokuSolver,并具有将每个方块的可能数字写入ArrayList的算法。然后第二个算法的工作原理如下:他找到具有最小可能数的正方形,设置该正方形上ArrayList中保存的第一个数字并进行递归,因此他再次开始定义每个正方形的可能数字拿一个具有最小可能性的那个并选择第一个将它放入该领域。在执行此操作时,for循环遍历每个正方形的可能数字。

import java.util.*;

public class SudokuSolver
{
    SudokuData data;

    public SudokuSolver(SudokuData d)
    {
        data = d;
    }


{
  /*Pseudoalgorithm:
  - Inserts the numbers 1-9 into a Collection called res
  - Looks at line x, which numbers are in there and erases them out of the      
        collection
  - Looks at column y, which numbers are in there and erases them out of the      
        collection
  - Looks in the 3x3 Square (x,y) which numbers are already in there and erases
        them out of the collection
  - Gives back the possible candidates for that field

 */

这里我初始化我的ArrayList。

     public ArrayList<Integer> offen(int x, int y)
 {
 ArrayList<Integer> res = new ArrayList<Integer>(); 
         /* The collection is saved in an ArrayList */
     int k = 0;

这里我只填写我的ArrayList中的数字1-9。

 for (int i=1;i<10;i++) 
     {
            res.add(i);
         }

现在出现了困难的部分:我将j从0循环到9,然后是k。该行与给定的x一致,j在列上运行,因此我得到给定行中的每个方格,并且在每个方格中我检查1-9中的每个数字。注意:索引从0到9,而元素从1-9开始,所以k必须是0-9,因为get() - 方法将索引作为输入。如果有任何合规性,我会从ArrayList中删除该元素。

   for (int j=0;j<9;j++) 
   {
     for (k=0;k<9;k++) 
     {
       if (this.data.feld[x][j] == (res.get(k)))
        res.remove(k);
     }

与列,常量列和j循环相同的内容。

     for (k=0;k<9;k++) 
     {
       if (this.data.feld[j][y] == res.get(k))
        res.remove(k);
     }
   }

现在我得到两个新变量的输入,只是因为我之前用错误的变量名输入了下面的代码部分。

   int m = x;
   int n = y;

这是3x3正方形的部分,我使用if条件,所以这只是9个部分中的一部分,我不想在这里发布它们,因为它们只是在一些常量上有所不同。我检查输入x,y是哪个方格,然后我在方块上循环并检查哪些数字,它们仍然在我的ArrayList中并删除它们。

   if (m<=2 && n<=2) 
   {
    for (m=0;m<3;m++) 
    {
      for (n=0;n<3;n++)
      {
        for (k=0;k<9;k++)
        {
          if (this.data.feld[m][n] == res.get(k))
           res.remove(k);
        }
      }
    }
   }

现在我返回ArrayList

  return res;
    }


//findSolution() finds a Solution
public boolean findSolution()
{
    /*Possible Strategy:
    - Find the square, which has the fewest possible candidates
      - If there are more than one candidates, who have the minimum of candidates,
            take any of them
      - If there are no more open candidates, there is a solution found. Return 
            true
    - Loop over the candidates of this square and by setting the first possible 
          candidate into this square[x][y]
    - Call the method findSolution() recursive to find in dependence of the set 
          value the values for the other fields 
      If there is a blind alley, take the next possible candidate (Backtracking!)

    */
int j = 0;
int k = 0;
int x = 0; // x coordinate of the field with the fewest open candidates
int y = 0; // y coordinate of the field with the fewest open candidates
int counter_offene_felder = 0;   // counts the number of open fields
int min = 9;   

我循环遍历j和k,查看可能候选者的数量是否大于0,这意味着我正在遍历整个数独字段并计算打开字段的数量。

for (j=0;j<9;j++) 
   {
     for (k=0;k<9;k++) 
     {
        if ( this.offen(j,k).size() >= 0) 
        {
          counter_offene_felder += 1;
        }

如果数字是&lt;比min = 9个可能的候选者,我把它作为min并保存该字段的坐标

        if ( (this.offen(j,k)).size() < min )
        {
          x = j;
          y = k;
        }
     }
   }

现在我用尽可能少的候选者初始化和ArrayList,并用我的offen-method将它们放入这个ArrayList中

  ArrayList<Integer> candidate_list = this.offen(x,y);
  for (k=0;k<this.offen(x,y).size();k++) 
  {  // runs over candidates
    int v = this.offen(x,y).get(k);   // takes the first candidate
    this.data.setNumber(x,y,v);   // writes the first candidate into square [x][y]
   this.findSolution();    // calls findSolution() recursive
  }

If there are no more open fields, I've found a solution

  if (counter_offene_felder == 0)
  {
    return true;
  }
  else return false;
}

}

问题是,我在第39行,在索引8大小8处得到一个IndexOutOfBounds异常。但我不知道为什么。 :(

2 个答案:

答案 0 :(得分:1)

不是肯定的,这是你收到错误的地方......但是当你做这样的事情时,你可能会遇到一个问题。

for (k=0;k<9;k++) 
 {
   if (this.data.feld[j][y] == res.get(k))
    res.remove(k);
 }

例如,假设在k = 1时if语句的计算结果为true。然后,您将从ArrayList中删除一个元素。然后当k = 8时,将抛出IndexOutOfBounds异常,因为ArrayList只包含8个元素(0-7)

假设没有其他线程会修改this.data.feld[][],那么在通过这个循环时你只会得到一个匹配...所以你可以这样做......

int match = -1;     

for (k=0;k<res.size();k++) {
       if (this.data.feld[j][y] == res.get(k)){
        match = k;
        break;
     }
}

if(match != -1)
     res.remove(match);

答案 1 :(得分:0)

我认为contains()方法将有助于消除此循环的异常。

尝试用以下代码替换代码:

for (m=0;m<3;m++) 
    {
      for (n=0;n<3;n++)
      {
        if (res.contains(this.data.field[m][n]))
            res.remove(res.indexOf(this.data.field[m][n]));
      }
}

它将迭代data.field,并检查ArrayList以查看它是否包含m,n的值。如果是,它将删除它。