数独生成器导致随机无限循环[C]

时间:2015-08-23 14:00:11

标签: c infinite-loop sudoku

我在C中制作一个数独生成器,但是当我启动程序时,它会在无限循环中随机出现。有时会打印所有行,有时只打印一行等等。(见下图) 这是代码 有什么问题?

#include <string.h>
#include <stdlib.h>
#include "sudoku.h"
#include <stdio.h>
#include <time.h>

int dimension = 9;

int main(int argc, char** argv){
  int dimension = 9;
  int j ,k,i ;
  int ** sudo =  malloc(sizeof(*sudo)*dimension);
  for ( j = 0; j< dimension; j++){
    sudo[j] =  malloc(sizeof(int)*dimension);
  }
    riempiSudoku(sudo);
  return 0;

void riempiSudoku(int** sudo){  //fill sudoku
  int j,i,k,f;
  int len; 
  //srand ( time(NULL));
  int ran;
  for (i=0;i<dimension;i++){
    for(j=0;j<dimension;j++){
      if(!thereisNumber(sudo, i,j)){
    printf("\nNon ci sono numeri\n");//no solution, stop the program
    exit(0);
      }
      printf("%d ", sudo[i][j]);
    }
    printf("\n");
  }
}


int checkRow(int** sudo, int row, int value){ //check if the number is in the row
  int i;
  for (i = 0; i<dimension; i++){
    if (sudo[row][i] == value)
      return 1;
  }
  return 0;
}

int checkCol(int** sudo, int col, int value){//check if the number is in the col
  int i;
  for (i = 0; i<dimension; i++){
    if (sudo[i][col] == value)
      return 1;
  }
  return 0;

}


int checkSquare(int** sudo, int row, int col, int value){
  int i, j;
  for(i= (row/3)*3; i<(row/3)*3 +3; i++){
    for(j=(col/3)*3; j<(col/3)*3 +3; j++){
      if(sudo[i][j] == value)
    return 1;
    }
  }
  return 0;

}
int thereisNumber(int** sudo, int i,int j){
  int options[dimension];
  int len;
  for (len=0; len<dimension; len++)
    options[len] = len + 1;             // populate the array with 1..9
  while (len) {
    int ran = rand() % len;         // select an index into the list
    int digit = options[ran];      // get the number from the available list
    if (checkSquare(sudo,i,j,digit) || checkRow(sudo,i,digit) || checkCol(sudo,j,digit))
        options[ran] = options[--len];  // remove digit from list
    else{
      sudo[i][j]= digit;
      return len>0;
    }
  }
  return 0; //thereisNumber(sudo,i,j-1);
}

这些是截图 http://imgur.com/lQpFOPf 这是gdb的结果 http://imgur.com/qp8omko

1 个答案:

答案 0 :(得分:1)

如果没有可能的解决方案,你的程序就会陷入僵局 - 正如@BLUEPIXY评论的那样。

但是你的程序无法检测到它,它不断尝试更多随机数。我建议使用卡片中使用的Fisher-Yates shuffle之类的东西,从可能的数组中删除不成功的候选者。

int options[dimension];
int len;
for (len=0; len<dimension; len++)
    options[len] = len + 1;             // populate the array with 1..9
while (len) {
    int ran = rand() % len;             // select an index into the list
    int digit = options[ran];           // get the number from the available list
    if (checkSquare(sudo,i,j,digit) || checkRow(sudo,i,digit) || checkCol(sudo,j,digit))
        options[ran] = options[--len];  // remove digit from list
    else break;
}
return len > 0;                         // 0 if failed to find digit

如果功能失败,您需要能够“撤消”数字展示位置的历史记录。那是你的下一个任务!

编辑而不是“撤消”功能,在每个数字位置都可以实现我展示的“可能性阵列”。解决方案比您想象的要复杂得多,可能需要递归解决方案。