2013-06-15 2 views
3

Я работаю над генератором головоломок sudoku в java, я написал этот класс, чтобы сгенерировать головоломку, но это неправильно генерирует загадку. Вот пример того, что я получаю:Генератор Java sudoku работает неправильно

puzzle

Как вы можете видеть, что это не является допустимым решением судоку. Но, глядя на мой код, я не понимаю, почему он не создает действительную загадку. Может кто-нибудь объяснить, почему это работает неправильно?

package sudoku; 

import java.util.Random; 

public class Puzzle { 

    // number generator 
    Random gen = new Random(); 

    // 9x9 puzzle 
    int puzzle[][] = new int[9][9]; 

    public int[][] generate() { 

     // add each number to the board 
     for (int x = 0; x < 9; x++) { 
      for (int y = 0; y < 9; y++) { 

       boolean isValid = false; 

       // keep generating new numbers until a valid number is found 
       while (isValid == false) { 

        // generate random number 1-9 
        int num = gen.nextInt(9) + 1; 

        // check if number is valid 
        if (checkRow(num, x) == true || checkCol(num, y) == true 
          || checkSection(num, x, y) == true) { 

         // add number to the board 
         puzzle[x][y] = num; 

         // exit loop 
         isValid = true; 
        } 
       } 
      } 
     } 

     return puzzle; 
    } 

    // check each element of the row for num, if num is found return false 
    private boolean checkRow(int num, int row) { 

     boolean valid = true; 
     for (int i = 0; i < 9; i++) { 
      if (puzzle[row][i] == num) { 
       valid = false; 
       break; 
      } 
     } 

     return valid; 
    } 

    // check each element of the column for num, if num is found return false 
    private boolean checkCol(int num, int col) { 

     boolean valid = true; 
     for (int i = 0; i < 9; i++) { 
      if (puzzle[i][col] == num) { 
       valid = false; 
       break; 
      } 
     } 

     return valid; 
    } 

    // check each element of the section for num, if num is found return false 
    private boolean checkSection(int num, int xPos, int yPos) { 

     int[][] section = new int[3][3]; 
     section = getSection(xPos, yPos); 

     boolean valid = true; 
     for (int i = 0; i < 3; i++) { 
      for (int j = 0; j < 3; j++) { 
       if (section[i][j] == num) { 
        valid = false; 
        break; 
       } 
      } 
     } 

     return valid; 
    } 

    // return the 3x3 section the given coordinates are in 
    private int[][] getSection(int xPos, int yPos) { 

     int xIndex = 0; 
     int yIndex = 0; 
     int[][] section = new int[3][3]; 

     // get x index 
     if (xPos == 0 || xPos == 3 || xPos == 6) { 
      xIndex = xPos; 
     } else if (xPos == 1 || xPos == 4 || xPos == 7) { 
      xIndex = xPos - 1; 
     } else if (xPos == 2 || xPos == 5 || xPos == 8) { 
      xIndex = xPos - 2; 
     } 

     // get y index 
     if (yPos == 0 || yPos == 3 || yPos == 6) { 
      yIndex = yPos; 
     } else if (yPos == 1 || yPos == 4 || yPos == 7) { 
      yIndex = yPos - 1; 
     } else if (yPos == 2 || yPos == 5 || yPos == 8) { 
      yIndex = yPos - 2; 
     } 

     int i = 0; 
     int j = 0; 
     // extract section from puzzle 
     for (int x = xIndex; x < 3; x++) { 
      for (int y = yIndex; y < 3; y++) { 
       section[x][y] = puzzle[i][j]; 
       i++; 
      } 
      j++; 
     } 

     return section; 

    } 
} 
+1

Ваш класс полностью процедурно написан, с любым следом объектной ориентации. Вы можете обнаружить, что ваш алгоритм легче устранять, если вы его модулировали в объекты, каждый из которых имеет свои собственные методы для тестирования и построения. Существительные в вашем проекте - «Головоломки», «Разделы», «Квадраты»; возможно, столбцы, строки и цифры. Они звучат как классы. Вместо отладки огромной монолитной процедуры было бы легче отлаживать поведение отдельных модулей. – scottb

+1

Это не ошибка, а в 'if (someCondition == true)' '' == true' часть избыточна, достаточно простого 'if (someCondition)'. – Pshemo

ответ

5

Недостаточно того, чтобы строка, столбец или раздел были действительны. Они ВСЕ ДОЛЖНЫ быть действительными. Таким образом, измените эту строку:

if (checkRow(num, x) == true || checkCol(num, y) == true || checkSection(num, x, y) == true) 

с

if (checkRow(num, x) == true && checkCol(num, y) == true && checkSection(num, x, y) == true) 

или просто в

if (checkRow(num, x) && checkCol(num, y) && checkSection(num, x, y)) { 
2

Там могут быть дополнительные ошибки, но эта линия явно не так:

if (checkRow(num, x) == true || checkCol(num, y) == true 
         || checkSection(num, x, y) == true) { 

Вы должны использовать && (boolean AND) здесь вместо || (логическое ИЛИ).

Смежные вопросы