簡體   English   中英

C數獨回溯解算器預檢查功能

[英]C sudoku backtracking solver precheck function

這是我在StackOverflow上的第一篇文章,因此,如果我做錯了什么,我深表歉意。 我是C語言的新手,所以我確定我的代碼在某些地方很丑陋,但是大多數代碼都能達到我的期望。 我無法使用precheck方法來檢查數獨板,然后才開始通過求解器邏輯對其進行檢查。 我正在使用文本字符串從文本文件重定向輸入

4 ..... 8.5.34 ......... 7 ...... 2 ..... 6 ..... 8.4 ...... 1 ..... ..6.3.7.5..2 ..... 1.4 ...... 4 ..... 8.5.3 .......... 7 ...... 2 ... ..6 ..... 8.4 ...... 1 ....... 6.3.7.5..2 ..... 1.5 ...... 4 ..... 8.5.3 .......... 7 ...... 2 ..... 6 ..... 8.4 ...... 1 ... x ... 6.3.7.5..2 ..... 1.4 ...... 417369825632158947958724316825437169791586432346912758289643571573291684164875293 417369825632158947958724316825437169791586432346912758289643.71572694

每個字符串(理想情況下)是81個字符,僅包含數字1-9和'。'。 我將字符串解析為臨時char數組,然后使用方法fillBoard將臨時數組中的char轉換為2d int數組。 完成此操作后,我將調用我的precheck方法。 如果填充的板未通過行,列和框檢查,則precheck方法將返回一個,表示難題不可解決(意味着應打印一條錯誤消息,並且程序應移至下一個字符串)。 由於某種原因,我的precheck方法即使對於應該可解決的字符串也返回一個。 我不確定為什么會這樣。 任何幫助,將不勝感激。 謝謝。

#include <stdio.h>
#include <string.h>

int alphaError = 0;

struct Point findEmpty(int board[9][9]);
int usedInBox(int board[9][9], int boxStartRow, int boxStartCol, int num);
int positionSafe(int board[9][9], int row, int col, int num);
int usedInCol(int board[9][9], int col, int num);
int usedInRow(int board[9][9], int row, int num);
int solvePuzzle(int board[9][9]);
int precheck(int board[9][9]);

int main()
{
  char c;
  int charCount = 0;
  int i = 0;
  char tempStr[100000];
  int board[9][9];

  while((fscanf(stdin, "%c", &c)) != EOF)
  {
    printf("%c", c);

    if(c != '\n')
    {
      if(isalpha(c))
      {
        alphaError = 1;
      }

      tempStr[i] = c;
      i++;
      charCount++;
    }
    else
    {
      if(charCount != 81 || alphaError == 1)
      {
        printf("Error\n\n");
        i = 0;
        charCount = 0;
        alphaError = 0;
      }
      else 
      {
        fillBoard(board, tempStr);
        printBoard(board);
        if(precheck(board) == 1)
        {
          printf("Error\n\n");
        }
        else
        {
          if(solvePuzzle(board) == 1)
          {
            printBoard(board);
          }
          else
          {
            printf("No solution\n\n");
          }
        }
        i = 0;
        charCount = 0;
      }
    }
  }
  return 0;
}

struct Point
{
  int x;
  int y;
} point;

struct Point findEmpty(int board[9][9])
{
  struct Point point1;
  point1.x = -1;
  point1.y = -1;
  int row, col;

  for(row = 0; row < 9; row++)
  {
    for(col = 0; col < 9; col++)
    {
      if(board[row][col] == 0)
      {
        point1.x = col;
        point1.y = row;
      }
    }
  }
  return point1;
}

int usedInBox(int board[9][9], int boxStartRow, int boxStartCol, int num)
{
  int row, col;

  for(row = 0; row < 3; row++)
  {
    for(col = 0; col < 3; col++)
    {
      if(board[row + boxStartRow][col + boxStartCol] == num)
      {
        return 1;
      }
    }
  }
  return 0;
}

int positionSafe(int board[9][9], int row, int col, int num)
{
  if((usedInRow(board, row, num)) == 0 && (usedInCol(board, col, num)) == 0 && (usedInBox(board, (row-row%3), (col-col%3), num)) == 0)
  {
    return 1;
  }
  else
  {
    return 0;
  }
}

int usedInCol(int board[9][9], int col, int num)
{
    int row;

    for(row = 0; row < 9; row++)
    {
    if(board[row][col] == num)
     {
       return 1;
     }
  }
  return 0;
}


int usedInRow(int board[9][9], int row, int num)
{
  int col;

  for(col = 0; col < 9; col++)
  {
    if(board[row][col] == num)
    {
      return 1;
    }
  }
  return 0;
}

int solvePuzzle(int board[9][9])
{
  int num;
  struct Point point2;

  point2 = findEmpty(board);
  if(point2.x == -1)
  {
    return 1;
  }

  for(num = 1; num <= 9; num++)
  {
    if(positionSafe(board, point2.y, point2.x, num) == 1)
    {
      board[point2.y][point2.x] = num;

      if(solvePuzzle(board) == 1)
      {
        return 1;
      }

      board[point2.y][point2.x] = 0;
    }
  }
  return 0;
}

void printBoard(int board[9][9]) 
{
  int i, j;
  for (i = 0; i < 9; i++) 
  {
    for (j = 0; j < 9; j++)
    {
      printf("%d", board[i][j]);
    }
  }
  printf("\n\n");
}  

void fillBoard(int board[9][9], char tempStr[100000])
{
  int i, j;
  int k = 0;

  for(i = 0; i < 9; i++) 
  {
    for(j = 0; j < 9; j++) 
    {
      if(tempStr[k] == '.')
      {
        board[i][j] = 0;
      }
      else
      {
        board[i][j] = (tempStr[k] - '0');
      }
      k++;
    }
  }
}

int precheck(int board[9][9])
{
  int i, j, num;

  for(i = 0; i < 9; i++)
  {
    for(j = 0; j < 9; j++)
    {
      if(board[i][j] != 0)
      {
        num = board[i][j];
        if(positionSafe(board, i, j, num) == 0)
        {
          return 1;
        }
      }
    }
  }
  return 0;
}

因此,您在已經裝滿的板上使用precheck嗎? 這可能是問題usedInCol ,因為usedInColusedInRowusedInBlock如果值已經存在,則將返回1。 因此,僅在填充電路板時才應使用precheck ,而不是在之后。 如果檢查從已填充的板上獲取的值,它將始終返回1。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM