0

次のプログラムで IndexOutOfBounds 例外が発生しました。次の 3 つのファイルで構成されます。

重要なのはそのうちの 2 つだけです。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;
    }

そのため、数独フィールドは 9x9 整数配列として割り当てられます。次のファイルは SudokuSolver と呼ばれ、各正方形の可能な数を ArrayList に書き込むアルゴリズムを持っています。次に、2 番目のアルゴリズムは次のように機能します。最小の可能な数を持つ正方形を見つけ、ArrayList に保存されている最初の数をその正方形に設定し、これを再帰的に実行するため、各正方形の可能な数の定義からやり直します。 、可能性の数が最も少ないものを取得し、最初のものを選択してそのフィールドに入れます。それを行っている間、for ループは、各正方形の可能な Numbers に対して実行されます。

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

以前に間違った変数名で以下のコード部分を入力したという理由だけで、2 つの新しい変数で入力を取得します。

   int m = x;
   int n = y;

ここに 3x3 の正方形の部分があります。if 条件でこれを行うので、これは 9 つの部分の 1 つにすぎません。ここにすべてを投稿したくはありません。いくつかの定数が異なるだけだからです。入力 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;
        }

数が < 最小 = 9 候補未満の場合、それを最小としてそのフィールドの座標を保存します

        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 行目の Index 8 Size 8 で IndexOutOfBounds Exception が発生することです。しかし、その理由はわかりません。:(

4

2 に答える 2

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 の値が含まれているかどうかを確認します。もしそうなら、それはそれを取り除きます。

于 2013-07-03T18:02:43.890 に答える